Python: using a module written in C

This is a brief tutorial for using a module written in C inside a Python program. It’s a summarized recipe fr those who want to run and test something fast without falling in reading the docs, but I recommend to read.

[1] http://docs.python.org/extending/extending.html
[2] http://docs.python.org/extending/building.html

Let’s write a module called spam, the same as the example in [1], our spammodule.c will look like this:

#include 
static PyObject *SpamError;
static PyObject *
spam_system(PyObject *self, PyObject *args){
    const char *command;
    int sts;
    if (!PyArg_ParseTuple(args, “s”, &command))
        return NULL;
    sts = system(command);
    return Py_BuildValue(”i”, sts);
}
static PyMethodDef SpamMethods[] = {
    {”system”,  spam_system, METH_VARARGS,
     “Execute a shell command.”},
    {NULL, NULL, 0, NULL}        /* Sentinel */
};
PyMODINIT_FUNC
initspam(void){
    PyObject *m;
    m = Py_InitModule(”spam”, SpamMethods);
    if (m == NULL)
        return;
    SpamError = PyErr_NewException(”spam.error”, NULL, NULL);
    Py_INCREF(SpamError);
    PyModule_AddObject(m, “error”, SpamError);
}

Ok, now, rather than compiling it by hand, let’s use an automated mechanism: distutils [2]. Edit a setup.py file which will be the “driver” for compile and make yur module in C importable from Python.

from distutils.core import setup, Extension
module1 = Extension('spam', sources = ['spammodule.c'])
setup(name = ‘PackageName’, version = ‘1.0′, description = ‘This is a demo package’,
          ext_modules = [module1])

Compile the C module using the driver: $ python setup.py build
An example of the output I get:

running build
running build_ext
building 'spam' extension
creating build
creating build/temp.linux-x86_64-2.6
gcc -pthread -fno-strict-aliasing -DNDEBUG -g -fwrapv -O3 -Wall -Wstrict-prototypes -fPIC -I/usr/include/python2.6 -c spammodule.c -o build/temp.linux-x86_64-2.6/spammodule.o
creating build/lib.linux-x86_64-2.6
gcc -pthread -shared build/temp.linux-x86_64-2.6/spammodule.o -L/usr/lib -lpython2.6 -o build/lib.linux-x86_64-2.6/spam.so

Test it!, depending on your platform and settings you’ll get a directory tree created, I’ll cd into mine:

$ cd build/lib.linux-x86_64-2.6
$ python
>>> import spam
>>> spam.system('echo "hello world"')
hello world
0
>>>

Tags: ,

Leave a Reply