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

时间:2011-02-23 11:59:11

标签: python c function callback call

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

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

2 个答案:

答案 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之后,它将包含一个整数。