从C调用Python函数时发生段错误

1 投票
2 回答
2655 浏览
提问于 2025-04-16 12:23

我想从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 个回答

1

我不太明白大家为什么在讨论GIL。你有在某个地方释放它吗?我注意到了一些可能的问题点,下面我会列出来,同时也会给出一些建议。

我发现你没有增加userData的引用计数。为什么呢?你不是在存储它吗?你为什么要把它存储在元组里?不如直接保留两个变量(一个用于回调,一个用于数据),然后增加它们的引用计数,这样你就能拥有一个引用了。

首先,检查一下你所有函数的返回值,看看它们是否是NULL。这样可以确保你的代码运行正常。使用PyObject_Print在代码的各个点打印你关心的对象,这样可以帮助你确认事情是否按预期进行,这也是个好主意。

根据你提到的段错误发生的地方,我猜测你在用PyObject_CallFunctionObjArgs调用回调函数时,传递的参数数量不对。你能再检查一下吗?也许可以把你的回调函数定义给我们看看,然后再检查一下调用的部分。

我还注意到另一个可能的问题,从命名来看,py_some_number听起来像是你期望一个Python整数对象。但实际上并不是这样。在PyArg_ParseTuple之后,它会包含一个整数。

5

当你在使用Python的C接口时遇到奇怪的情况,最好再仔细检查一下你是否正确管理了全局解释器锁(也叫“GIL”)的状态。这个锁是用来控制多个线程同时访问Python解释器的,确保不会出现混乱。你可以查看这个链接了解更多信息:http://docs.python.org/c-api/init.html#thread-state-and-the-global-interpreter-lock

撰写回答