Python Programming/Extending with C

Previous: HTTP Tools Index Next: Extending with C++

This gives a minimal Example on how to Extend Python with C. Linux is used for building (feel free to extend it for other Platforms). If you have any problems, please report them (e.g. on the dicussion page), I will check back in a while and try to sort them out.

Using the Python/C APIEdit

On an Ubuntu system, you might need to run

$ sudo apt-get install python-dev           // this command ensures that you can use the line #include <Python.h>

A minimal exampleEdit

The minimal example we will create now is very similar in behaviour to the following python snippet:

 def say_hello(name):
     "Greet somebody."
     print "Hello %s!" % name

The C source code (hellomodule.c)Edit

#include <Python.h>
 
static PyObject*
say_hello(PyObject* self, PyObject* args)
{
    const char* name;
 
    if (!PyArg_ParseTuple(args, "s", &name))
        return NULL;
 
    printf("Hello %s!\n", name);
 
    Py_RETURN_NONE;
}
 
static PyMethodDef HelloMethods[] =
{
     {"say_hello", say_hello, METH_VARARGS, "Greet somebody."},
     {NULL, NULL, 0, NULL}
};
 
PyMODINIT_FUNC
inithello(void)
{
     (void) Py_InitModule("hello", HelloMethods);
}

Building the extension module with GCC for LinuxEdit

To build our extension module we create the file setup.py like:

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

Now we can build our module with

python setup.py build

The module hello.so will end up in build/lib.linux-i686-x.y.

Building the extension module with GCC for Microsoft WindowsEdit

Microsoft Windows users can use MinGW to compile this from cmd.exe using a similar method to Linux user, as shown above. Assuming gcc is in the PATH environment variable, type:

python setup.py build -cmingw32

The module hello.pyd will end up in build\lib.win32-x.y, which is a Python Dynamic Module (similar to a DLL).

An alternate way of building the module in Windows is to build a DLL. (This method does not need an extension module file). From cmd.exe, type:

gcc -c  hellomodule.c -I/PythonXY/include
gcc -shared hellomodule.o -L/PythonXY/libs -lpythonXY -o hello.dll

where XY represents the version of Python, such as "24" for version 2.4.

Building the extension module using Microsoft Visual C++Edit

With VC8 distutils is broken. We will use cl.exe from a command prompt instead:

cl /LD hellomodule.c /Ic:\Python24\include c:\Python24\libs\python24.lib /link/out:hello.dll

Using the extension moduleEdit

Change to the subdirectory where the file `hello.so` resides. In an interactive python session you can use the module as follows.

>>> import hello
>>> hello.say_hello("World")
Hello World!

A module for calculating fibonacci numbersEdit

The C source code (fibmodule.c)Edit

#include <Python.h>
 
int
_fib(int n)
{
    if (n < 2)
        return n;
    else
        return _fib(n-1) + _fib(n-2);
}
 
static PyObject*
fib(PyObject* self, PyObject* args)
{
    int n;
 
    if (!PyArg_ParseTuple(args, "i", &n))
        return NULL;
 
    return Py_BuildValue("i", _fib(n));
}
 
static PyMethodDef FibMethods[] = {
    {"fib", fib, METH_VARARGS, "Calculate the Fibonacci numbers."},
    {NULL, NULL, 0, NULL}
};
 
PyMODINIT_FUNC
initfib(void)
{
    (void) Py_InitModule("fib", FibMethods);
}

The build script (setup.py)Edit

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

How to use it?Edit

>>> import fib
>>> fib.fib(10)
55

Using SWIGEdit

Creating the previous example using SWIG is much more straight forward. To follow this path you need to get SWIG up and running first. To install it on an Ubuntu system, you might need to run the following commands

$ sudo apt-get install libboost-python-dev 
$ sudo apt-get install python-dev

After that create two files.

/*hellomodule.c*/
 
#include <stdio.h>
 
void say_hello(const char* name) {
    printf("Hello %s!\n", name);
}
/*hello.i*/
 
%module hello
extern void say_hello(const char* name);

Now comes the more difficult part, gluing it all together.

First we need to let SWIG do its work.

swig -python hello.i

This gives us the files `hello.py` and `hello_wrap.c`.

The next step is compiling (substitute /usr/include/python2.4/ with the correct path for your setup!).

gcc -fpic -c hellomodule.c hello_wrap.c -I/usr/include/python2.4/

Now linking and we are done!

gcc -shared hellomodule.o hello_wrap.o -o _hello.so

The module is used in the following way.

>>> import hello
>>> hello.say_hello("World")
Hello World!
Last modified on 6 March 2014, at 04:19