Thursday, August 22, 2013

Sending a Python Function to C++ and Calling Within C++

I thought I would share something I figured out how to do recently. In C++ I have a nice function that numerically integrates a given function. I wanted to be able to call this quadrature routine from Python while feeding it a Python function (callable). For the sake of simplicity I will show a much smaller example here. I realize there are quadrature routines in scipy.integrate but I wanted the flexibility of my C++ routine as well.

Suppose we have a very simply Python function called "myfunc":
def myfunc(x):
    return 2.0 * x;
I want to be able to send this function to C++ and use it within my C++ program. To do this I wrote the following C++ code:
#include "Python.h"

static PyObject *execMyPyFunc(PyObject *self, PyObject *args) {
 PyObject *Fx, *pyresult;
 double x, result;

 PyArg_ParseTuple(args, "dO", &x, &Fx);
 pyresult = PyObject_CallFunction(Fx, "d", x);
 result = PyFloat_AsDouble(pyresult);
 return Py_BuildValue("d", result);
}

static PyMethodDef C_API_TestMethods[] = {
 {"execMyPyFunc", execMyPyFunc, METH_VARARGS, "Add documentation here...."},
 {NULL, NULL}
};

PyMODINIT_FUNC initC_API_Test(void) {
 Py_InitModule("C_API_Test", C_API_TestMethods);
}
This creates a DLL (or .pyd for Python) module called "C_API_Test" that I can import into Python. This module contains the function "execMyPyFunc" that I can use within my Python scripts. The function "execMyPyfunc" takes two arguments:
  1. a double precision scalar
  2. a python function
I make use of PyObject_CallFunction. My Python script looks like this:
from C_API_Test import execMyPyFunc

def myfunc(x):
    return 2.0 * x;
    
fx = execMyPyFunc(1.28,myfunc)
print fx
And it returns 2.56! Voila! Note: I haven't read up on PY_INCREF & Py_DECREF. They may need to be added here. If someone knows, please let me know. Thanks!

No comments: