For a less trivial example, consider the following Python code:
class Name(object):
def __init__(self, forname='', surname=''):
self.forname = forname
self.surname = surname
def name(self):
return "%s %s"%(self.forname, self.surname)
This is a perfectly fine Python class with no particular reason to be rewritten in C, but as we need an example, that's exactly what we'll do:
#include <Python.h>
#include <structmember.h>
typedef struct {
PyObject_HEAD
PyObject *firstname;
PyObject *lastname;
} NameObject;
static int
Name_init(NameObject *self, PyObject *args, PyObject *kwds)
{
PyObject *firstname = Py_None;
PyObject *lastname = Py_None;
PyObject *tmp = NULL;
static char *kwlist[] = {"firstname", "lastname", NULL};
if (!PyArg_ParseTupleAndKeywords(args, kwds, "|OO", kwlist,
&firstname, &lastname))
return -1;
tmp = self->firstname;
if (firstname == Py_None) {
self->firstname = PyString_FromString("");
}
else {
Py_INCREF(firstname);
self->firstname = firstname;
}
Py_XDECREF(tmp);
tmp = self->lastname;
if (lastname == Py_None) {
self->lastname = PyString_FromString("");
}
else {
Py_INCREF(lastname);
self->lastname = lastname;
}
Py_XDECREF(tmp);
return 0;
}
static PyMemberDef Name_members[] = {
{"firstname", T_OBJECT_EX, offsetof(NameObject, firstname), 0,
"first name"},
{"lastname", T_OBJECT_EX, offsetof(NameObject, lastname), 0,
"last name"},
{NULL} /* Sentinel */
};
static PyObject *
Name_name(NameObject *self, PyObject *unused)
{
PyObject *args = NULL;
PyObject *format = NULL;
PyObject *result = NULL;
format = PyString_FromString("%s %s");
if (format == NULL)
goto fail;
if (self->firstname == NULL) {
PyErr_SetString(PyExc_AttributeError, "firstname");
goto fail;
}
if (self->lastname == NULL) {
PyErr_SetString(PyExc_AttributeError, "lastname");
goto fail;
}
args = Py_BuildValue("OO", self->firstname, self->lastname);
if (args == NULL)
goto fail;
result = PyString_Format(format, args);
fail:
Py_XDECREF(format);
Py_XDECREF(args);
return result;
}
static PyMethodDef Name_methods[] = {
{"name", (PyCFunction)Name_name, METH_NOARGS,
"Return the name, combining the firstname and lastname."
},
{NULL}
};
static char Name_doc[] =
"boo.";
static PyTypeObject NameObjectType = {
PyObject_HEAD_INIT(NULL)
0, /* ob_size */
"name.Name", /* tp_name */
sizeof(NameObject), /* tp_basicsize */
0, /* tp_itemsize */
0, /* tp_dealloc */
0, /* tp_print */
0, /* tp_getattr */
0, /* tp_setattr */
0, /* tp_compare */
0, /* tp_repr */
0, /* tp_as_number */
0, /* tp_as_sequence */
0, /* tp_as_mapping */
0, /* tp_hash */
0, /* tp_call */
0, /* tp_str */
0, /* tp_getattro */
0, /* tp_setattro */
0, /* tp_as_buffer */
Py_TPFLAGS_DEFAULT, /* tp_flags */
Name_doc, /* tp_doc */
0, /* tp_traverse */
0, /* tp_clear */
0, /* tp_richcompare */
0, /* tp_weaklistoffset */
0, /* tp_iter */
0, /* tp_iternext */
Name_methods, /* tp_methods */
Name_members, /* tp_members */
0, /* tp_getset */
0, /* tp_base */
0, /* tp_dict */
0, /* tp_descr_get */
0, /* tp_descr_set */
0, /* tp_dictoffset */
(initproc)Name_init, /* tp_init */
};
PyMODINIT_FUNC
initname(void)
{
PyObject* m;
NameObjectType.tp_new = PyType_GenericNew;
if (PyType_Ready(&NameObjectType) < 0)
return;
m = Py_InitModule3("name", NULL,
"XXX");
if (m == NULL)
return;
Py_INCREF(&NameObjectType);
PyModule_AddObject(m, "Name", (PyObject *)&NameObjectType);
}
THIS DOCUMENT IS A DRAFT! Comments to mwh@python.net please.