所以,我想从C调用Python回调函数。
在某些时候,函数被发送到C并打包成像这样的元组
PyObject *userData = Py_BuildValue("Oi",py_callback,some_number);
在该地区的某个地方,我也Py_INCREF(py_callback)
在程序的某个稍后时间,我想调用该函数
PyObject *py_callback;
int some_number;
PyArg_ParseTuple((PyObject*)userData,"Oi",&py_callback,&some_number); // returns true
PyObject *py_result = PyObject_CallFunctionObjArgs(py_callback,
/* ... */
NULL);
并且最后一次调用会引发分段错误。你有什么想法,为什么会做这样的事情?
答案 0 :(得分:5)
当从Python C API获得奇怪的行为时,总是值得仔细检查您是否正确管理全局解释器锁(又称“GIL”)的状态:http://docs.python.org/c-api/init.html#thread-state-and-the-global-interpreter-lock
答案 1 :(得分:1)
我不确定为什么每个人都在谈论GIL。你在任何地方发布它吗?我注意到一些可能的问题点,我将在下面列出。它与建议混合在一起。
我注意到你没有增加userData
的引用次数。为什么不?你存的不是吗?为什么要将它存储在元组中?为什么不保留两个变量(用于回调和数据),然后增加它们的引用量,以便你拥有一个引用?
首先,检查所有函数的返回值,看它们是否为NULL
。这样可以确保您实际上正常运行。使用PyObject_Print
在代码中的所有点打印您感兴趣的对象也是一个好主意,以确保事情按预期进行。
根据您对段错误发生位置的评论,我的猜测是,当您使用PyObject_CallFunctionObjArgs
调用时,您将错误数量的参数传递给回调函数。你能仔细检查一下吗?也许告诉我们你的回调函数定义,然后再次检查调用。
我看到的另一个可能的问题是,从命名,py_some_number
听起来像你期望一个Python整数对象。不是这种情况。在PyArg_ParseTuple
之后,它将包含一个整数。