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.
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
/**/ /*********************************************************************
* A simple C library file, with a single function, "message",
* which is to be made available for use in Python programs.
* There is nothing about Python here--this C function can be
* called from a C program, as well as Python (with glue code).
*
* 一個簡單的C語言庫檔案,只有一個函數,"message",
* 將會成為可被Python程式使用的函數。
* 這裡沒有任何Python相關的東西——這個C函數可以
* 由C程式調用,也可以由Python程式調用(加上粘合代碼後)。
*********************************************************************/
char *
message( char * label) /**/ /* this is exported */
... {
strcpy(result, "Hello, "); /**//* build up C string */
strcat(result, label); /**//* add passed-in label */
return result; /**//* return a temporary */
}
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
/**/ /********************************************************************
* Define hellolib.c exports to the C namespace, not to Python
* programs--the latter is defined by a method registration
* table in a Python extension module's code, not by this .h;
*
* 定義hellolib.c輸出到C語言的符號(不是輸出到Python程式)。
* 輸出到Python程式的符號在Python擴充模組代碼中由一個方法註冊表定義,
* 而不是在這個.h檔案中。
********************************************************************/
extern char * message( char * label);
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
/**/ /******************************************************
* Swig module description file, for a C lib file.
* Generate by saying "swig -python 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:
Sets the module's name as known to Python importers.
%module 設定模組名,Python匯入的就是這個名字。
%{...%}
Encloses code added to generated wrapper file verbatim.
%{...%}括起來的代碼將原封不動地添加到產生的封裝檔案中。
extern statements
Declare exports in normal ANSI C/C++ syntax.
extern語句用標準的ANSI C/C++文法聲明輸出的符號。
%include
Makes SWIG scan another file (-I flags give search paths).
%include命令SWIG掃描另一個檔案(可以用-I標誌給出搜尋路徑)。
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
##################################################################
# Use SWIG to integrate hellolib.c