9

我已经阅读了 Python C-API 的文档,甚至还编写了一些扩展模块。但是,当涉及从 C 函数返回 Python 对象时,我仍然不清楚确切的语义。

Python 文档中的有限示例通常显示一个 C 函数,该函数返回Py_BuildValue. 现在,Py_BuildValue返回一个New Reference, 并将这个引用的所有权转移给解释器。那么,我可以由此推断,返回给 Python 的任何对象都必须是一个新的引用,并且从 C 函数返回一个对象与将对象的所有权转移给解释器是一样的,这是一个通用规则吗?

如果是这样,那么返回一个已经被某物拥有的对象的情况呢?例如,假设您编写了一个接受 a PyObject*which is a的 C 函数tuple,然后调用PyTuple_GetItem它并返回结果。 PyTuple_GetItem返回一个借用的引用- 意味着该项目仍然由元组“拥有”。那么,在将结果返回给解释器之前,返回类似结果的 C 函数PyTuple_GetItem是否必须得到结果?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?
}
4

1 回答 1

6

Python 期望你向它公开的任何函数都返回一个的引用,是的。如果你只有一个借来的参考,你必须打电话Py_INCREF给一个新的参考。如果你返回一个借用的引用,Python 将继续调用Py_DECREF(当它完成引用时),最终这将导致对象在它仍在使用时被释放。

(在解释器退出期间发生“最终”释放的情况并不少见,在这种情况下它可能会被忽视,但返回借用的引用仍然是一个错误。)

于 2011-05-30T13:17:33.737 回答