22.6. The SWIG Integration Code Generator
But don't do that. As you can probably tell, manual coding of C extensions can become fairly involved (this is almost inevitable in C language work). I've introduced the basics in this chapter thus far so that you understand the underlying structure. But today, C extensions are usually better and more easily implemented with a tool that generates all the required integration glue code automatically. There are a variety of such tools for use in the Python world, including SIP, SWIG, and Boost.Python; we'll explore alternatives at the end of this chapter. Of these, the SWIG system is likely still the most widely used.
The Simplified Wrapper and Interface Generator (SWIG) is an open source system created by Dave Beazley and now developed by its community, much like Python. It uses C and C++ type declarations to generate complete C extension modules that integrate existing libraries for use in Python scripts. The generated C (and C++) extension modules are complete: they automatically handle data conversion, error protocols, reference-count management, and more.
That is, SWIG is a program that automatically generates all the glue code needed to plug C and C++ components into Python programs; simply run SWIG, compile its output, and your extension work is done. You still have to manage compilation and linking details, but the rest of the C extension task is largely performed by SWIG.
22.6.1. A Simple SWIG Example
To use SIWG, instead of writing all that C code in the prior sections, write the C function you want to use from Python without any Python integration logic at all, as though it is to be used from C alone. For instance, Example 22-5 is a recoding of Example 22-1 as a straight C function.
Example 22-5. PP3E\Integrate\Extend\HelloLib\hellolib.c
While you're at it, define the usual C header file to declare the function externally, as shown in Example 22-6. This is probably overkill for such a small example, but it will prove a point.
Example 22-6. PP3E\Integrate\Extend\HelloLib\hellolib.h
Now, instead of all the Python extension glue code shown in the prior sections, simply write a SWIG type declarations input file, as in Example 22-7.
Example 22-7. PP3E\Integrate\Extend\Swig\hellolib.i
This file spells out the C function's type signature. In general, SWIG scans files containing ANSI C and C++ declarations. Its input file can take the form of an interface description file (usually with a .i suffix) or a C/C++ header or source file. Interface files like this one are the most common input form; they can contain comments in C or C++ format, type declarations just like standard header files, and SWIG directives that all start with %. For example:
In this example, SWIG could also be made to read the hellolib.h header file of Example 22-6 directly. But one of the advantages of writing special SWIG input files like hellolib.i is that you can pick and choose which functions are wrapped and exported to Python, and you may use directives to gain more control over the generation process.
SWIG is a utility program that you run from your build scripts; it is not a programming language, so there is not much more to show here. Simply add a step to your makefile that runs SWIG and compile its output to be linked with Python. Example 22-8 shows one way to do it on Cygwin.
Example 22-8. PP3E\Integrate\Extend\Swig\makefile.hellolib-swig
When run on the hellolib.i input file by this makefile, SWIG generates two files:
The former is named for the input file, and the later per the %module directive. Really, SWIG generates two modules today: it uses a combination of Python and C code to achieve the integration. Scripts ultimately import the generated Python module file, which internally imports the generated and compiled C module.
To build the C module, the makefile runs a compile after running SWIG, and then combines the result with the original C library code:
.../PP3E/Integrate/Extend/Swig$ make -f makefile.hellolib-swig force rm -f *.dll *.o *.pyc core hellolib_wrap.c hellowrap.py .../PP3E/Integrate/Extend/Swig$ ls Environ Shadow hellolib.i makefile.hellolib-swig .../PP3E/Integrate/Extend/Swig$ make -f makefile.hellolib-swig swig -python -I../HelloLib hellolib.i gcc hellolib_wrap.c -g -I../HelloLib -I/usr/include/python2.4 -c -o hellolib_wrap.o gcc -shared hellolib_wrap.o ../HelloLib/hellolib.o \ -L/usr/bin -lpython2.4 -o _hellowrap.dll .../PP3E/Integrate/Extend/Swig$ ls Environ _hellowrap.dll hellolib_wrap.c hellowrap.py Shadow hellolib.i hellolib_wrap.o makefile.hellolib-swig
More specifically, the makefile runs SWIG over the input file, compiles the generated C glue code file into a .o object file, and then links it with hellolib.c's compiled object file to produce _hellowrap.dll. The result is a dynamically loaded C extension module file ready to be imported by Python code. Like all modules, _hellowrap.dll must, along with hellowrap.py, be placed in a directory on your Python module search path (a period [.] will suffice if you're working in the directory where you compile).
Notice that the .dll file must be built with a leading underscore in its name; as of SWIG 1.3.14, this is required because SWIG also created the .py file of the same name without the underscore.
As usual in C development, you may have to barter with the makefile to get it to work on your system. Once you've run the makefile, though, you are finished. The generated C module is used exactly like the manually coded version shown before, except that SWIG has taken care of the complicated parts automatically:
.../PP3E/Integrate/Extend/Swig$ python >>> import hellowrap # import glue + library file >>> hellowrap.message('swig world') # cwd always searched on imports 'Hello, swig world' >>> hellowrap._ _file_ _ 'hellowrap.py' >>> dir(hellowrap) ['_ _builtins_ _', '_ _doc_ _', '_ _file_ _', '_ _name_ _', '_hellowrap', ...]
In other words, once you learn how to use SWIG, you can largely forget all the integration coding details introduced in this chapter. In fact, SWIG is so adept at generating Python glue code that it's usually much easier and less error prone to code C extensions for Python as purely C- or C++-based libraries first, and later add them to Python by running their header files through SWIG, as demonstrated here.
22.6.2. SWIG Details
Of course, you must have SWIG before you can run SWIG; it's not part of Python itself. Unless it is already on your system, fetch SWIG off the Web and run its installer or build it from its source code. To do the latter, you'll need a C++ compiler; see SWIG's README file and web site for more details. SWIG is a command-line program and generally can be run just by saying the following:
swig -python hellolib.i
Along the way in this chapter, we'll meet a few more SWIG-based alternatives to the remaining examples. By way of introduction, here is a quick look at a few more SWIG highlights:
Consult the SWIG Python user manual for the full scoop on its features. SWIG's feature set and implementation are both prone to change over time (e.g., its pointers are no longer strings, and Python new-style classes are employed in dual-mode proxy classes), so we'll defer to its documentation for more internals information.
Later in this chapter, we'll see SWIG in action two more times, wrapping up C environment calls and a C++ class. Although the SWIG examples in this book are simple, you should also know that SWIG handles industrial-strength libraries just as easily. For instance, Python developers have successfully used SWIG to integrate libraries as complex as Windows extensions and commonly used graphics APIs such as OpenGL.
SWIG can also generate integration code for other scripting languages such as Tcl and Perl. In fact, one of its underlying goals is to make components independent of scripting language choicesC/C++ libraries can be plugged into whatever scripting language you prefer to use (I prefer to use Python, but I might be biased). SWIG's support for things such as classes seems strongest for Python, though, probably because Python is considered to be strong in the classes department. As a language-neutral integration tool, SWIG addresses some of the same goals as systems such as COM and CORBA (described in Chapter 23), but it provides a code generation-based alternative rather than an object model.
You can find SWIG by a web search or by visiting its current home page on the Web at http://www.swig.org. Along with full source code, SWIG comes with outstanding documentation (including documentation specifically for Python). The documentation also describes how to build SWIG extensions with other platforms and compilers, including standard Windows without Cygwin.