Section 22.4. A Simple C Extension Module


22.4. A Simple C Extension Module

At least that's the short story; we need to turn to some code to make this more concrete. C types generally export a C module with a constructor function. Because of that, and because they are simpler, let's start off by studying the basics of C module coding with a quick example.

As mentioned, when you add new or existing C components to Python, you need to code an interface ("glue") logic layer in C that handles cross-language dispatching and data translation. The C source file in Example 22-1 shows how to code one by hand. It implements a simple C extension module named hello for use in Python scripts, with a function named message that simply returns its input string argument with extra text prepended. Python scripts will call this function as usual, but this one is coded in C, not in Python.

Example 22-1. PP3E\Integrate\Extend\Hello\hello.c

 /********************************************************************  * A simple C extension module for Python, called "hello"; compile  * this into a ".so" on python path, import and call hello.message;  ********************************************************************/ #include <Python.h> #include <string.h> /* module functions */ static PyObject *                                 /* returns object */ message(PyObject *self, PyObject *args)           /* self unused in modules */ {                                                 /* args from Python call */     char *fromPython, result[64];     if (! PyArg_Parse(args, "(s)", &fromPython))  /* convert Python -> C */         return NULL;                              /* null=raise exception */     else {         strcpy(result, "Hello, ");                /* build up C string */         strcat(result, fromPython);               /* add passed Python string */         return Py_BuildValue("s", result);        /* convert C -> Python */     } } /* registration table  */ static struct PyMethodDef hello_methods[] = {     {"message", message, 1},       /* method name, C func ptr, always-tuple */     {NULL, NULL}                   /* end of table marker */ }; , /* module initializer */ void inithello( )                       /* called on first import */ {                                      /* name matters if loaded dynamically */     (void) Py_InitModule("hello", hello_methods);   /* mod name, table ptr */ } 

Ultimately, Python code will call this C file's message function, passing in a string object and getting back a new string object. First, though, it has to be somehow linked into the Python interpreter. To use this C file in a Python script, compile it into a dynamically loadable object file (e.g., hello.so on Linux, hello.dll under Cygwin on Windows) with a makefile like the one listed in Example 22-2, and drop the resulting object file into a directory listed on your module import search path exactly as though it were a .py or .pyc file.

Example 22-2. PP3E\Integrate\Extend\Hello\makefile.hello

 ############################################################# # Compile hello.c into a shareable object file on Cygwin, # to be loaded dynamically when first imported by Python. ############################################################# PYLIB = /usr/bin PYINC = /usr/include/python2.4 hello.dll: hello.c         gcc hello.c -g -I$(PYINC) -shared -L$(PYLIB) -lpython2.4 -o hello.dll clean:         rm -f hello.dll core 

This is a Cygwin makefile that uses gcc to compile our C code; other platforms are analogous but will vary. As mentioned in Chapter 5 in the sidebar "Forking on Windows with Cygwin," Cygwin provides a Unix-like environment and libraries on Windows. To work along with the examples here, either see http://www.cygwin.com for download details or change the makefiles listed per your compiler and platform requirements. Be sure to include the path to Python's install directory with -I flags to access Python include (a.k.a. header) files, as well as the path to the Python binary library file with -L flags, if needed.

Now, to use the makefile in Example 22-2 to build the extension module in Example 22-1, simply type a standard make command at your shell (the Cygwin shell is used here):

 .../PP3E/Integrate/Extend/Hello$ make -f makefile.hello gcc hello.c -g -I/usr/include/python2.4 -shared                    -L/usr/bin -lpython2.4 -o hello.dll 

This generates a shareable object filea .dll under Cygwin on Windows. When compiled this way, Python automatically loads and links the C module when it is first imported by a Python script. At import time, the .dll binary library file will be located in a directory on the Python import search path, just like a .py file. Because Python always searches the current working directory on imports, this chapter's examples will run from the directory you compile them in (.) without any file copies or moves. In larger systems, you will generally place compiled extensions in a directory listed in PYTHONPATH or .pth files instead.

Finally, to call the C function from a Python program, simply import the module hello and call its hello.message function with a string; you'll get back a normal Python string:

 .../PP3E/Integrate/Extend/Hello$ python >>> import hello                                   # import a C module >>> hello.message('world')                         # call a C function 'Hello, world' >>> hello.message('extending') 'Hello, extending' 

And that's ityou've just called an integrated C module's function from Python. The most important thing to notice here is that the C function looks exactly as if it were coded in Python. Python callers send and receive normal string objects from the call; the Python interpreter handles routing calls to the C function, and the C function itself handles Python/C data conversion chores.

In fact, there is little to distinguish hello as a C extension module at all, apart from its filename. Python code imports the module and fetches its attributes as if it had been written in Python. C extension modules even respond to dir calls as usual and have the standard module and filename attributes (though the filename doesn't end in a .py or .pyc this time around):

 >>> dir(hello)                                     # C module attributes ['_ _doc_ _', '_ _file_ _', '_ _name_ _', 'message'] >>> hello._ _name_ _, hello._ _file_ _ ('hello', 'hello.dll') >>> hello.message                                  # a C function object <built-in function message> >>> hello                                          # a C module object <module 'hello' from 'hello.dll'> 

Like any module in Python, you can also access the C extension from a script file. The Python file in Example 22-3, for instance, imports and uses the C extension module.

Example 22-3. PP3E\Integrate\Extend\Hello\hellouse.py

 import hello print hello.message('C') print hello.message('module ' + hello._ _file_ _) for i in range(3):     print hello.message(str(i)) 

Run this script as any otherwhen the script first imports the module hello, Python automatically finds the C module's .dll object file in a directory on the module search path and links it into the process dynamically. All of this script's output represents strings returned from the C function in the file hello.c:

 .../PP3E/Integrate/Extend/Hello$ python hellouse.py Hello, C Hello, module /cygdrive/c/.../PP3E/Integrate/Extend/Hello/hello.dll Hello, 0 Hello, 1 Hello, 2 




Programming Python
Programming Python
ISBN: 0596009259
EAN: 2147483647
Year: 2004
Pages: 270
Authors: Mark Lutz

flylib.com © 2008-2017.
If you may any questions please contact us: flylib@qtcs.net