Python Programming/Extending with C

From Wikibooks, open books for an open world
< Python Programming
Jump to: navigation, search

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 API[edit]

On an Ubuntu system, you might need to run

$ sudo apt-get install python-dev

This command installs you the python developement package and ensures that you can use the line #include <Python.h> in the C source code. On other systems like openSUSE the needed package calls python-devel and can be installed by using zypper:

$ sudo zypper install python-devel

A minimal example[edit]

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 Linux[edit]

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 Windows[edit]

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 module[edit]

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 numbers[edit]

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 SWIG[edit]

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!