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 ]
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
(list, PyInt_FromLong(b)); // Why FromLong?
= 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"},

// Initialize the module
(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.
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 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