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. PP3EIntegrateExtendHellohello.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. PP3EIntegrateExtendHellomakefile.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 file—a
.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 it—you’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. PP3EIntegrateExtendHellohellouse.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 other—when 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
3.133.159.223