Embedding python in cpp: How to get a C-pointer to a python function (not to a PyObject)?
Embedding python in cpp: How to get a C-pointer to a python function (not to a PyObject)?
I want to enable the writing of user python-plugins for an existing C++ application. The main application will emit signals using boost::signals2 that trigger the execution of the users python code. I set up a working sample where an initialize method in the users python module is being called. The user can subscribe to signals calling a "connect"-method:
import ctypes
CALLBACK_VOID_FUNC = CFUNCTYPE(None)
def myVoidHandler():
print("myVoidHandler (python)")
def initialize(myCHandle):
global myCDll, callback1
myCDll = ctypes.CDLL("CppEventsd", handle = myCHandle)
[...]
callback1 = CALLBACK_VOID_FUNC(myVoidHandler)
myCDll.connect(b"readyToGo", callback1)
[...]
The signature of the connect method:
extern "C" __declspec(dllexport) bool connect(char* signalName, void(*pF)())
Now the python function myVoidHandler could be called from cpp just like this:
pF();
But more importantly, pF can be connected to a boost signal.
However I want to spare the users going through this (and spare myself the support requests because they did not get it quite right), so I want to connect the python functions from the cpp side by using a naming convention for the functions/slots.
I can easily retrieve a PyObjet pointer to the python callback:
PyObject *pModule, *pDict, *pVoidHandlerF;
pModule = PyImport_Import(pName);
pDict = PyModule_GetDict(pModule);
pVoidHandlerF = PyDict_GetItemString(pDict, "myVoidHandler");
BUT I cannot figure out how to get the actual function pointer (equivalent to pF) from the cpp side! Some transformation seems to be going on in the python to Cpp transition.
Any ideas?
pVoidHandlerF
sig.connect([=]() PyObject_CallObject(pVoidHandlerF, NULL); );
YES! That´s the better solution anyway, because I can then also check for the return of PyObject_CallObject and print a useful message if something goes wrong! I´ll go with that.
– uha
Aug 25 at 21:02
Okay, I have moved the comment to an answer. Feel free to accept it :)
– pschill
Aug 27 at 8:26
1 Answer
1
Instead of connecting directly to the python function pointer, you could create your own C++ function that uses the python C-API to invoke the python function. Here is an example:
boost::signals2::signal<void(void)>& sig = [...];
PyObject* pVoidHandlerF = [...];
sig.connect([=]()
PyObject_CallObject(pVoidHandlerF, NULL);
);
This allows you to do other stuff on the C++ side, for example, passing arguments, returning values, checking for errors, etc.
By clicking "Post Your Answer", you acknowledge that you have read our updated terms of service, privacy policy and cookie policy, and that your continued use of the website is subject to these policies.
Instead of connecting directly to the python function pointer, you could create your own C++ function that invokes
pVoidHandlerF
, for example, by using a C++ lambda:sig.connect([=]() PyObject_CallObject(pVoidHandlerF, NULL); );
– pschill
Aug 23 at 13:47