-
Notifications
You must be signed in to change notification settings - Fork 51
Description
I have a C++ library with one function that takes a function pointer (let's call it register(my_callback_t cb)) as a callback. I want to wrap this with PyBindGen so that I can call the register function from Python, passing in a Python function object as the function to call in the callback.
Based on examples, I created the ForwardWrapperBase derived class for the my_callback_t function type, where I map the Python caller's PyObject * for the callback to the internal C++ callback. Then, when the internal C++ callback is called by my library, I manually call the Python object again, using the following pattern:
PyGILState_STATE gstate;
gstate = (PyEval_ThreadsInitialized() ? PyGILState_Ensure() : (PyGILState_STATE) 0);
// Convert C++ arguments to Python objects
PyObject *arglist = Py_BuildValue("(sssO)", id.c_str(), name.c_str(), value.c_str(), valid ? Py_True: Py_False);
// Using the ID, find the PyObject * which corresponds to the registered callback
PyObject *result = PyObject_CallObject(cb_map.at(id), arglist);
Py_DECREF(arglist);
if (NULL == result)
{
if (NULL == PyErr_Occurred())
{
printf("@@@ PythonBinging: Unknown error occurred in subscription callback\n");
}
else
{
PyErr_Print();
}
}
Py_XDECREF(result);
if (PyEval_ThreadsInitialized())
{
PyGILState_Release(gstate);
}The above works well for the most part, but occasionally causes SEGFLT in the main python thread after the entirety of both the Python and C++ callbacks complete.
The two questions I have are:
- Do you see something wrong with the above?
- I noticed that there is a thing called
ReverseWrapperBasein PyBindGen, which seems to be related to C code calling back into Python. However, I cannot figure out how to use it and there do not appear to be any examples using it. Can you please provide an example?