ePolyglot: Examination and development of multilanguage programming using Eiffel, Python, and Haskell | ||
---|---|---|
Prev | Chapter 11. Calling Eiffel from Python | Next |
We're doing well so far: we have exported Eiffel functions into a form usable for SWIG, and used SWIG to generate the source code necessary for marshaling all the data values around. We are now ready to create a Python-compatible module for use.
Fortunately, this part is actually relatively simple. The Python distribution comes with a rather complex make fragment, Makefile.pre.in, which contains a hideous conglomeration of sed code generation, many odd targets, and quite a bit of symbol manipulation to wrap a set of C source files into a dynamically-loadable library which can be imported just like any other Python library. We simply list all affected C source code files in a Setup.in file, so:
Example 11-6. The Setup.in file for the eiffel_glue module
*shared* eiffel_glue eiffel-glue_wrap.c python_client_wrap.c wrap_python_macros.c swigptr.c called_from_python*.c |
The file eiffel-glue_wrap.c is code generated by SWIG for the new module; swigptr.c is code used by SWIG to handle translation of C pointers to and from Python strings. The python_client_wrap.c and wrap_python_macros.c files are SWIG-generated code for Eiffel/Python interoperability (and are probably not necessary unless the Eiffel classes being scripted are also able to call Python code!). Finally, the called_from_python*.c files represent the source code generated by the SmallEiffel compile_to_c program, run on the Eiffel code to be exported. Whew!
This entire mess can be automated somewhat by the use of a rather long make target:
Example 11-7. The make target for eiffel_gluemodule.so
EIFFEL_GLUEMODULE_SOURCES = Setup.in Makefile.pre.in eiffel-glue.h eiffel-glue_wrap.c python_client_wrap.c $(SWIGPTRC) $(CLIBS) eiffel_gluemodule.so : $(EIFFEL_GLUEMODULE_SOURCES) rm -rf temp; \ mkdir temp; \ cp $(EIFFEL_GLUEMODULE_SOURCES) temp; \ cp called_from_python* temp; \ cd temp; \ make -f Makefile.pre.in boot; \ make; \ cp eiffel_gluemodule.so ..; \ cd ..; \ rm -rf temp |
At long last, our Eiffel program functionality has been exposed to Python, in the form of a single Python module (eiffel_glue). This module can even be imported into the Python interpreter without an Eiffel program, although doing so will not work correctly (see the next chapter for a description of scripting Eiffel entirely with C). From within Python code, we can now attempt to access any exported feature of our Eiffel code.
It should be noted that doing this is actually rather risky, particularly as far as Eiffel is concerned. In a language which prides itself on run-time correctness and type safety, this sort of gaping hole (which allows the C developer to call from_external on any Eiffel object, with disastrous results) raises all kinds of warning flags. It would be better, then, to avoid exposing this directly--preferably by creating a solution similar to that used in the Eiffel-to-Python sections: shadow classes in Python, referencing the correct methods through an opaque object pointer.