从C调用Python函数时发生段错误
我想从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 个回答
我不太明白大家为什么在讨论GIL。你有在某个地方释放它吗?我注意到了一些可能的问题点,下面我会列出来,同时也会给出一些建议。
我发现你没有增加userData
的引用计数。为什么呢?你不是在存储它吗?你为什么要把它存储在元组里?不如直接保留两个变量(一个用于回调,一个用于数据),然后增加它们的引用计数,这样你就能拥有一个引用了。
首先,检查一下你所有函数的返回值,看看它们是否是NULL
。这样可以确保你的代码运行正常。使用PyObject_Print
在代码的各个点打印你关心的对象,这样可以帮助你确认事情是否按预期进行,这也是个好主意。
根据你提到的段错误发生的地方,我猜测你在用PyObject_CallFunctionObjArgs
调用回调函数时,传递的参数数量不对。你能再检查一下吗?也许可以把你的回调函数定义给我们看看,然后再检查一下调用的部分。
我还注意到另一个可能的问题,从命名来看,py_some_number
听起来像是你期望一个Python整数对象。但实际上并不是这样。在PyArg_ParseTuple
之后,它会包含一个整数。
当你在使用Python的C接口时遇到奇怪的情况,最好再仔细检查一下你是否正确管理了全局解释器锁(也叫“GIL”)的状态。这个锁是用来控制多个线程同时访问Python解释器的,确保不会出现混乱。你可以查看这个链接了解更多信息:http://docs.python.org/c-api/init.html#thread-state-and-the-global-interpreter-lock