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])
.