python - 从 Python C 扩展函数返回参数时需要 INCREF?

标签 python python-c-api python-extensions

这个问题很简单,但有助于加深我的理解。我知道 C 扩展函数的参数在 C 代码期间保证是实时引用(除非手动 DECREFed)。但是,如果我有一个 C 扩展代码返回一个存在于它的参数列表中的 PyObject*,我是否需要在返回它之前 INCREF 参数?即,以下两项中哪一项是正确的:

static PyObject return_item(PyObject *self, PyObject *item)
{
    // manipulate item
    return item;
}

static PyObject return_item(PyObject *self, PyObject *item)
{
    // manipulate item
    Py_INCREF(item);
    return item;
}

基于 https://docs.python.org/3/extending/extending.html#ownership-rules ,它说

The object reference returned from a C function that is called from Python must be an owned reference — ownership is transferred from the function to its caller.

Returning objects to Python from C我假设是后者(INCREFing 是要走的路)但我想确定。

最佳答案

如果有人从 Python 调用 return_item 函数,他们可能会这样做:

something = Something()
something_else = return_item(something)
del something

如果 return_item 没有返回传入的参数,而是返回其他东西,你会期望此时传入的 something 应该被释放内存,因为它的引用计数降为零。

如果你不 Py_INCREF 并返回同一个对象,那仍然会发生 - 对象的引用计数将下降到 0,你将在 something_else 中有一个无效对象>.

TL;DR:是的,您应该 Py_INCREF,因为您通过从函数返回该对象创建了另一个引用。

关于python - 从 Python C 扩展函数返回参数时需要 INCREF?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/57661466/

相关文章:

python - 如何获取当前的 PyInterpreterState?

Python CApi 引用计数详细信息

python - 显示对象表 django

python - 如何获得指向通用 PyObject* 内数据的指针?

python - __pycache__ 文件夹应该包含在生产容器中吗?

python - 将 C++ 扩展 header 与 Python 包源分发捆绑在一起

python - 如何从 C 的 PyObject 类型的函数将值从 C 返回到 python?

python - 将 Setuptools 与 C 扩展一起用作包的一部分

c# - python 到 c# (关于服务器请求)

python - Docker 撰写 mysql 连接失败