Wednesday, May 27, 2009

A Simple Python Module

Writing a Python Module in C is simple and quite effective. The following is a module to solve the Fibonacci series up to n. The C version of this module is four times faster than the Python equivalent.

[ All code taken from http://superjared.com/entry/anatomy-python-c-module/ ]
include <Python.h>

// Returns a list of the Fibonacci series up to n in args
static PyObject *fib(PyObject *self, PyObject *args)
{
int a = 0, b = 1, c, n;

// Parse args for a single integer
if (!PyArg_ParseTuple(args, "i", &n))
return NULL;

// Create a list to store the numbers using PyList
PyObject *list = PyList_New(0);

// Calculate the Fibonnaci series
while (b < n)
{
// Append b as an int to list
PyList_Append
(list, PyInt_FromLong(b)); // Why FromLong?
c
= a + b;
a
= b;
b
= c;
}

// returns a PyObject*
return list;
}

// Some array of PyMethodDefs
PyMethodDef methods[] = {
{"fib", fib, METH_VARARGS, "Returns a fibonnaci sequence as a list"},
{NULL, NULL, 0, NULL}
};

// Initialize the module
PyMODINIT_FUNC
initfib
()
{
(void) Py_InitModule("fib", methods);
}
This code was pretty easy and made sense. There are a few arcane functions in here that I can't make sense of. The C function type is PyObject*. This is because:
All object types are extensions of PyObject. This is a type which contains the information Python needs to treat a pointer to an object as an object.
(http://docs.python.org/c-api/structures.html)
I'm going to need to look through the C API and get my stuff down straight before tomorrow when I begin writing the c_datetime64.c and c_timedelta64.c files.

After creating the C file, you have to create a Python setup.py file which uses distutils to "compile" (I think that's the right word) the C module and make it usuable with Python. The file for the Fibonacci example looks like this:
from distutils.core import setup, Extension

# Tells distutils that our module is located in fibonacci.c
setup(name = "Fib",
version = "1.0",
ext_modules = [Extension("fib", ["fibonacci.c"])])

This uses distutils to run some setup function. I won't be researching too much into distutils until later. For now, I understand that it can create Extensions from C files. Here's that Fibonacci code in action:
>>> import fib
>>> fib.fib(2131)
[1, 1, 2, 3, 5, 8, 13, 21, 34, 55, 89, 144, 233, 377, 610, 987, 1597]
>>> fib.fib(10000)
[1, 1, 2, 3, 5, 8, 13, 21, 34, 55, 89, 144, 233, 377, 610, 987, 1597, 2584, 4181, 6765]

No comments:

Post a Comment