0

I Have a C++ code that calls a function named "function" of a python script named "filename".

PyObject module= PyImport_ImportModule("filename");
PyObject *python_fn = PyObject_GetAttrString(module, (char *)"function");
PyObject *args = PyTuple_New(0);
PyObject_CallObject(python_fn , args);

The function is called correctly. Now I want to be able to pass to the python module a pointer to a C function. I tried with the PyImport_AppendInittab as described here but I had no luck.

Any suggestion?

Thanks H.

Halbarad
  • 73
  • 1
  • 5
  • How is this c++11? – babu646 Apr 10 '18 at 14:48
  • I am open to solutions in C++11. – Halbarad Apr 10 '18 at 14:54
  • It isn't clear what you're actually trying to do here - the code you have has is pretty unrelated to passing a C function pointer. Do you want to pass a C function pointer to a function that expects a Python callable? (`Inittab` is to do with setting up built-in modules without needing an .so file so I don't think that applies here) – DavidW Apr 11 '18 at 20:17
  • The code is what I have right now. It is not code that is not functioning.I would like to add the functionality that I can pass the C function pointer and call that function from python. Sorry for not making that clear. – Halbarad Apr 12 '18 at 06:58

1 Answers1

0

In order to pass a C/C++ function pointer to a Python function you need to convert it into a Python object (since all arguments to Python functions must be Python objects). You can create a DIY version with an outline something like this:

typedef struct {
   PyObject_HEAD
   int (*ptr)(int, int); // assuming this matches the signature of the function pointer
} MyFuncPtr;

PyObject* Call_MyFuncPtr(MyFuncPtr* self, PyObject* args, PyObject* kwargs) {
  // implementation goes here...
  //  you probably want to convert the Python arguments to C with PyArg_ParseTupleAndKeywords
  //  call the function
  //  then convert the C return value back to a PyObject* and return that
}

The associated PyTypeObject is defined pretty as in the tutorial - the only change you need to make is to set tp_call to Call_MyFuncPtr so that the type is callable in Python (you may need a cast here - the signatures don't quite match because of the type of the first argument). You don't need to add it to a module object (since it'll only be accessible from C anyway) but you do need to call PyType_Ready on it.

You'd then allocate it using

MyFuncPtr* mfp = PyObject_New(MyFuncPtr,&MyFuncPtr_Type)
mfp->ptr = // some matching C/C++ function

and pass it is an argument to Python using a standard C API function call.


It's possible that there you want to avoid doing this yourself and use an existing library. For C++, Boost Python defines a nice wrapper that automatically does this, as does PyBind11. You might also be able to use the Ctypes or CFFI libraries, but it isn't immediately obvious to me how you interface with them from C or C++.

DavidW
  • 29,336
  • 6
  • 55
  • 86