尝试从C调用Python函数时的Segfault

所以,我想从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); 

并且最后一次调用会引发分段错误。 你有什么想法,为什么会做这样的事情?

当从Python C API获得奇怪的行为时,总是值得仔细检查您是否正确管理全局解释器锁(又称“GIL”)的状态: http : //docs.python.org/c-api/ init.html#线程状态和最全球翻译锁

我不确定为什么每个人都在谈论GIL。 你在任何地方发布它吗? 我注意到一些可能的问题点,我将在下面列出。 它与建议混合在一起。

我注意到你没有增加userData的引用计数。 为什么不? 你存的不是吗? 为什么要将它存储在元组中? 为什么不保留两个变量(用于回调和数据),然后增加它们的引用量,以便你拥有一个引用?

首先,检查所有函数的返回值,看它们是否为NULL 。 这样可以确保您实际上正常运行。 使用PyObject_Print在代码中的所有点打印您感兴趣的对象也是一个好主意,以确保事情按预期进行。

根据你对段错误发生位置的评论,我的猜测是,当你用PyObject_CallFunctionObjArgs调用它时,你将错误数量的参数传递给回调函数。 你能仔细检查一下吗? 也许向我们展示你的回调函数定义,然后再次检查调用。

我看到的另一个可能的问题是,从命名, py_some_number听起来像你期望一个Python整数对象。 不是这种情况。 在PyArg_ParseTuple ,它将包含一个整数。