我已经阅读了Python C-API的文档,甚至还编写了一些扩展模块。但是,在从C函数返回Python对象时,我对于确切的语义仍然有点不清楚。
Python文档中的有限示例通常显示一个返回Py_BuildValue
结果的C函数。现在,Py_BuildValue
返回New Reference
,并将此引用的所有权转移给解释器。那么,我可以从中推断出一般规则是返回到Python的任何对象必须是新引用,并且从C函数返回对象与转移对象的所有权相同转到口译员?
如果是这样,那么返回已经拥有某个东西的对象的情况呢?例如,假设您编写了一个C函数,该函数接收PyObject*
tuple
,并在其上调用PyTuple_GetItem
并返回结果。 PyTuple_GetItem
返回借用的引用 - 意味着该项仍然由元组“拥有”。那么,在将结果返回给解释器之前,返回类似PyTuple_GetItem
之类结果的C函数是否必须INCREF
结果?
例如:
static PyObject* my_extension_module(PyObject* tup)
{
PyObject* item = PyTuple_GetItem(tup, 1);
if (!item) { /* handle error */ }
return item; // <--- DO WE NEED TO INCREF BEFORE RETURNING HERE?
}
答案 0 :(得分:5)
Python期望您向其公开的任何函数都返回 new 引用,是的。如果您只有借用的参考,则必须致电Py_INCREF
以提供新的参考。如果你返回一个借用的引用,Python将继续调用Py_DECREF
(当它完成引用时),并最终导致该对象在它仍在使用时被释放。
(在解释器退出期间发生“最终”释放的情况并不罕见,在这种情况下可能会被忽视,但返回借用的引用仍然是错误的。)