Cha*_*nya 15 c c++ python callback python-c-api
我试图从C++调用python类中的方法.调用它的C++方法是C++回调.
在我尝试调用python方法时,在这个方法中,它正在给予segmentation fault.
我已经在一个全局变量中保存了一个python函数实例
// (pFunc is global variable of type PyObject*)
pFunc = PyDict_GetItemString(pDict, "PlxMsgWrapper");
Run Code Online (Sandbox Code Playgroud)
其中PlxMsgWrapper是一个python方法,将在回调中使用.
在回调中,参数创建为
PyObject* args = PyTuple_Pack(2, PyString_FromString(header.c_str()),
PyString_FromString(payload.c_str()));
Run Code Online (Sandbox Code Playgroud)
在创建时
PyObject * pInstance = PyObject_CallObject(pFunc, args);
Run Code Online (Sandbox Code Playgroud)
在这一行中它给出了分段错误.在此之后,实际的python方法被称为
PyObject* recv_msg_func = PyObject_GetAttrString(module, (char *)"recvCallback");
args = PyTuple_Pack(1, pInstance);
PyObject_CallObject(recv_msg_func, args);
Run Code Online (Sandbox Code Playgroud)
msh*_*ldt 32
如果从C/C++回调调用Python函数,则需要执行一些操作.首先,当你保存你的python函数对象时,你需要增加引用计数:
Py_INCREF(pFunc)
Run Code Online (Sandbox Code Playgroud)
否则,Python不知道您持有对象引用,它可能会垃圾收集它,当您尝试从回调中使用它时会导致分段错误.
接下来你需要关心的是调用C/C++回调时正在运行的线程.如果你从另一个非Python创建的线程(即在套接字上接收数据的C/C++线程)回调,那么在调用任何Python API函数之前,你必须获得Python的全局解释器锁(GIL).否则你的程序的行为是不确定的.要获得GIL,您需要:
void callback() {
PyGILState_STATE gstate;
gstate = PyGILState_Ensure();
// Get args, etc.
// Call your Python function object
PyObject * pInstance = PyObject_CallObject(pFunc, args);
// Do any other needed Python API operations
// Release the thread. No Python API allowed beyond this point.
PyGILState_Release(gstate);
}
Run Code Online (Sandbox Code Playgroud)
此外,在扩展模块的init函数中,您应该执行以下操作以确保正确初始化线程:
// Make sure the GIL has been created since we need to acquire it in our
// callback to safely call into the python application.
if (! PyEval_ThreadsInitialized()) {
PyEval_InitThreads();
}
Run Code Online (Sandbox Code Playgroud)
否则,当您尝试从非Python线程获取GIL时,可能会发生崩溃和奇怪的行为.
有关此内容的更多详细信息,请参阅非Python创建的线程.
| 归档时间: |
|
| 查看次数: |
12372 次 |
| 最近记录: |