Thursday, April 01, 2010

Extending Python with C or C++

I'm learning how to write C++ code that can extend python.

To help myself and possibly anyone else, I'm going to write what I've learned so far.

the first thing that's required is to include the python header. On ubuntu if you haven't installed it yet, you can with this:
sudo install python-dev


Then you can start editing a cpp file with whatever your fave editor is. I choose you, vim!

$ vi knightmodule.cpp
Apparently for historical reasons the file is called XXXmodule, though if you have a "long" module name you can just use the name, like knight.cpp.

Continuing on, the first line in your file needs to be:
#include
which contains all the useful bits you need to make a good extension.


#include

extern "C"{

static PyObject * whosayni(PyObject *self, PyObject *args){
const char * knight;

if(!PyArg_ParseTuple(args, "s", &knight))
return NULL;

printf("%s is a knight who says, \"Ni!\"", knight);

Py_RETURN_NONE;
}

static PyMethodDef MyMethods[] = {
{"whosayni", whosayni, METH_VARARGS,
"Param knight: prints knight is a knight who says, \"Ni!\""},
{NULL, NULL, 0, "Testing"}
};

PyMODINIT_FUNC

initmyknights(void){
(void) Py_InitModule("Hello", MyMethods);
}

} // end extern


Then we create a python build script. It can be named anything you want, but convention dictates setup.py

$ vi setup.py


then


from distutils.core import setup, Extension

module1 = Extension('knight', sources = ['knightmodule.cpp'])

setup (name = 'Knights',
version = '1.0',
description = 'They say ni!',
ext_modules = [module1])


And fire it off with
$ python setup.py build


it will put your file in build/lib.linux-i686-2.6/knight.so - you can copy this .so file anywhere or navigate to the directory. When you're in the same dir as your knight.so


$ python
Python 2.6.4 (r264:75706, Dec 7 2009, 18:45:15)
[GCC 4.4.1] on linux2
Type "help", "copyright", "credits" or "license" for more information.
>>> import knight
>>> knight.whosayni("Lancelot")
Lancelot is a knight who says, "Ni!">>>


Notice that the >>> is on the same line? That's because we didn't add a newline at the end of our print string.

So go ahead and edit that, rebuild your knight, and import again (just make sure if you copied it that you copy it again). You should get something like this:

>>> knight.whosayni('Richard')
Richard is a knight who says, "Ni!"


Now you've written your very first C++ extension for Python.

Keep looking for updates when I come back and explain what all this stuff does.

Labels: , , , ,