Helping ordinary people create extraordinary websites!
HOME TUTORIALS SCRIPTS WEB HOSTING BLOG FORUM
Get Our Newsletter
Email:

Extending Python and Zope in C

By Michael Roberts
2004-12-04


Writing the Code

So how do we actually write code that Python knows how to use, you ask? The foomain.c file (you can call it anything you want, of course) contains three things: a method table, an initialization function, and the rest of the code. The method table simply associates names with functions, and tells Python what parameter-passing mechanism each function uses (you have a choice between a regular list of positional arguments, or a mix of positional and keyword arguments). Python calls the initialization function when the module loads. It does whatever initialization is required for the module, if any, but most crucially, it also passes a pointer to the method table back to Python.

So let's look at the C code for our little foo module.


#include <Python.h>

/* Define the method table. */
static PyObject *foo_bar(PyObject *self, PyObject *args);
static PyMethodDef FooMethods[] = {
{"bar", foo_bar, METH_VARARGS},
{NULL, NULL}
};
/* Here's the initialization function. We don't need to do anything
for our own needs, but Python needs that method table. */
void initfoo()
{
(void) Py_InitModule("foo", FooMethods);
}
/* Finally, let's do something ... involved ... as an example function. */
static PyObject *foo_bar(PyObject *self, PyObject *args)
{
char *string;
int len;
if (!PyArg_ParseTuple(args, "s", &string))
return NULL;
len = strlen(string);
return Py_BuildValue("i", len);
}
A closer look
Let's look at that code for a moment. First, notice that you have to include Python.h. Unless you have your include path set up to find that file, you may need to include an -I flag in your Setup file to point to it.

The initialization function must be named init<module name>, in our case initfoo. The initialization function's name is, of course, all that Python knows about your module when it loads it, and that's why its name is so constrained. The init function, by the way, should be the only global identifier in the file that isn't declared static. This is more crucial for static linking than dynamic, because a non-static identifier will be globally visible. This isn't too much of a problem with dynamic linking, but if you're linking everything at compile-time, you will very likely run into name collisions if you don't make everything static that you can.

When we get down to the actual code, take a look at how parameters are processed, and how the return value is passed. Everything, of course, is a PyObject -- an object on the Python heap. What you get in your arguments are a reference to the "this" object (this is for object methods and is NULL for plain old functions like bar()) and an argument tuple in args. You retrieve your arguments using PyArg_ParseTuple, then you pass your result back with Py_BuildValue. These functions and more are documented in the "Python/C API" section of the Python documentation. Unfortunately, there is no simple listing of functions by name; instead the document is arranged by topic.

Notice also that in case of error, the function returns NULL. A NULL return signals an error; to work with Python even better, though, you should raise an exception. I'll refer you to the documentation on how that works.

Tutorial Pages:
» The Best of Both Worlds
» Extending Python for Fun and Profit
» Writing the Code
» Building the Extension
» Taking it to Zope
» Creating an External Method
» Zope scripts: Cliff Notes version
» Going all out With a Product
» Where to go From Here
» Resources


First published by IBM DeveloperWorks


 | Bookmark
Related Tutorials:
» Python and Java - A Side by Side Comparison
» Learn Python in 10 Minutes
» Python 201 - (Slightly) Advanced Python Topics
» Python 101 - Introduction to Python
» Google Sitemaps
» Python 101