#include "Python.h" /* type-definition & utility-macros */ typedef struct { PyObject_HEAD PyObject *car, *cdr; } cons_cell; staticforward PyTypeObject cons_type; /* a typetesting macro (we don't use it here) */ #define is_cons(v) ((v)->ob_type == &cons_type) /* macros to access car & cdr, both as lvalues & rvalues */ #define carof(v) (((cons_cell*)(v))->car) #define cdrof(v) (((cons_cell*)(v))->cdr) /* ctor (factory-function) and dtor */ static cons_cell* cons_new(PyObject *car, PyObject *cdr) { cons_cell *cons = PyObject_NEW(cons_cell, &cons_type); if(cons) { cons->car = car; Py_INCREF(car); /* INCREF when holding a PyObject* */ cons->cdr = cdr; Py_INCREF(cdr); /* ditto */ } return cons; } static void cons_dealloc(cons_cell* cons) { /* DECREF when releasing previously-held PyObject*'s */ Py_DECREF(carof(cons)); Py_DECREF(cdrof(cons)); PyObject_DEL(cons); } /* Python type-object */ statichere PyTypeObject cons_type = { PyObject_HEAD_INIT(0) /* initialize to 0 to ensure Win32 portability */ 0, /*ob_size*/ "cons", /*tp_name*/ sizeof(cons_cell), /*tp_basicsize*/ 0, /*tp_itemsize*/ /* methods */ (destructor)cons_dealloc, /*tp_dealloc*/ /* implied by ISO C: all zeros thereafter */ }; /* module-functions */ static PyObject* cons(PyObject *self, PyObject *args) /* the exposed factory-function */ { PyObject *car, *cdr; if(!PyArg_ParseTuple(args, "OO", &car, &cdr)) return 0; return (PyObject*)cons_new(car, cdr); } static PyObject* car(PyObject *self, PyObject *args) /* car-accessor */ { PyObject *cons; if(!PyArg_ParseTuple(args, "O!", &cons_type, &cons)) /* type-checked */ return 0; return Py_BuildValue("O", carof(cons)); } static PyObject* cdr(PyObject *self, PyObject *args) /* cdr-accessor */ { PyObject *cons; if(!PyArg_ParseTuple(args, "O!", &cons_type, &cons)) /* type-checked */ return 0; return Py_BuildValue("O", cdrof(cons)); } static PyMethodDef elemlist_methods[] = { {"cons", cons, METH_VARARGS}, {"car", car, METH_VARARGS}, {"cdr", cdr, METH_VARARGS}, {0, 0} }; /* module entry-point (module-initialization) function */ PyMODINIT_FUNC initelemlist(void) { /* Create the module and add the functions */ PyObject *m = Py_InitModule("elemlist", elemlist_methods); /* Finish initializing the type-objects */ cons_type.ob_type = &PyType_Type; }
The header file Python.h makes the Python API's accessible in the code.
car(), cdr() and cons() are the functions exposed
at Python level so that they can be called after importing the elemlist
module.
The C implementation of these functions take arguments as Python objects.
To do anything with them in the C function we have to convert them to C values.
elemlist_methods
is the method table for the module. The method table is
passed to the interpreter in the module's initialization function, initelemlist().
The initialization function must be named initname(), where name is the
name of the module, and should be the only non-static item defined in the module file.
The PyMODINIT_FUNC declares the function as void
return type, declares any special
linkage declarations required by the platform, and for C++ declares the function
as extern "C"
. When the Python program imports module elemlist for the
first time, initelemlist() is called.
The MMP file contents for the above source is as follows:
TARGETTYPE dll TARGET kf_elemlist.pyd CAPABILITY LocalServices NetworkServices ReadUserData WriteUserData UserEnvironment NOSTRICTDEF DEFFILE elemlist.def /* If global data is present in the extension module then this macro should be * defined in the mmp file. */ EPOCALLOWDLLDATA SYSTEMINCLUDE \epoc32\include\python25 SYSTEMINCLUDE \epoc32\include\stdapis SYSTEMINCLUDE \epoc32\include LIBRARY python25.lib SOURCEPATH ..\src SOURCE elemlist.c
An example usage of the 'elemlist' extension module can be:
from elemlist import * cell = cons(1, 2) print "car(cell) :", car(cell) print "cdr(cell) :", cdr(cell)
See About this document... for information on suggesting changes.