reference count management every step of the way. In return for all the work, C gets
to use the techniques shown in this file to reuse any Python class.
Of course, this example could be more complex in practice. As mentioned earlier, you
generally need to check the return value of every Python API call to make sure it didn’t
fail. The module import call in this C code, for instance, can fail easily if the module
isn’t on the search path; if you don’t trap the NULL pointer result, your program will
almost certainly crash when it tries to use the pointer (at least eventually). Exam-
ple 20-35 is a recoding of Example 20-34 with full error-checking; it’s big, but it’s
robust.
Example 20-35. PP4E\Integrate\Embed\Pyclasss\objects-err.c
#include <Python.h>
#include <stdio.h>
#define error(msg) do { printf("%s\n", msg); exit(1); } while (1)
main() {
/ run objects with low-level calls and full error checking /
char arg1="sir", arg2="robin", cstr;
PyObject pmod, pclass, pargs, pinst, pmeth, *pres;
/ instance = module.klass() /
Py_Initialize();
pmod = PyImport_ImportModule("module"); / fetch module /
if (pmod == NULL)
error("Can't load module");
pclass = PyObject_GetAttrString(pmod, "klass"); / fetch module.class /
Py_DECREF(pmod);
if (pclass == NULL)
error("Can't get module.klass");
pargs = Py_BuildValue("()");
if (pargs == NULL) {
Py_DECREF(pclass);
error("Can't build arguments list");
}
pinst = PyEval_CallObject(pclass, pargs); / call class() /
Py_DECREF(pclass);
Py_DECREF(pargs);
if (pinst == NULL)
error("Error calling module.klass()");
/ result = instance.method(x,y) /
pmeth = PyObject_GetAttrString(pinst, "method"); / fetch bound method /
Py_DECREF(pinst);
if (pmeth == NULL)
error("Can't fetch klass.method");
pargs = Py_BuildValue("(ss)", arg1, arg2); / convert to Python /
if (pargs == NULL) {
Py_DECREF(pmeth);
error("Can't build arguments list");
Using Python Classes in C| 1537