Python Programming/Extending with C
< Python ProgrammingThis 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
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
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)
#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
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
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++
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
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
The C source code (fibmodule.c)
#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)
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?
>>> import fib >>> fib.fib(10) 55
Using SWIG
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 swig $ 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 -lpython
The module is used in the following way.
>>> import hello >>> hello.say_hello("World") Hello World!