Extending C with Python
Sometimes it is useful to borrow functionality that is implemented in a Python library. To do this we can initialize an embedded Python interpreter, and then load functions.
Getting Started
The basic structure of initializing the interpreter and loading the python-hostlist module is as follows
#include <Python.h> int main(int argc, char *argv[]) { PyObject *pModule; Py_SetProgramName(argv[0]); Py_Initialize(); /* import module */ pModule = PyImport_ImportModule("hostlist"); if (pModule == NULL) { if (PyErr_Occurred()) PyErr_Print(); exit(1); } Py_DECREF(pModule); Py_Finalize(); return 0; }
Now we can build using
CFLAGS != python2.7-config --cflags LDFLAGS != python2.7-config --ldflags hostlist: hostlist.c cc ${CFLAGS} -L/usr/local/lib ${LDFLAGS} $< -o $@
Calling Functions
Python arguments are return values are all
PyOjbect
pointers, and we can use the well-documented set of
standard functions
to instantiate data and validate/convert outputs
PyObject* expand_hostlist(PyObject *pModule, PyObject* pHostlistExp) {
PyObject *pFunc;
PyObject *pArgs, *pValue;
/* get pointer to function */
pFunc = PyObject_GetAttrString(pModule, "expand_hostlist");
if (!pFunc) {
if (PyErr_Occurred())
PyErr_Print();
exit(1);
}
/* construct an argument list */
pArgs = PyTuple_New(1);
PyTuple_SetItem(pArgs, 0, pHostlistExp);
pValue = PyObject_CallObject(pFunc, pArgs);
Py_DECREF(pArgs);
Py_DECREF(pFunc);
/* ensure the return value is what we expect */
if (pValue && PyList_Check(pValue)) {
return pValue;
}
return NULL;
}
To call this function, simply convert a C string into a Python object using
PyString_FromString(argv[1]).