从 C 返回对象到 Python

发布于 2024-11-10 08:14:24 字数 854 浏览 4 评论 0原文

我阅读了 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?
}

I've read the documentation for the Python C-API, and even written a few extension modules. However, I'm still a bit unclear on the exact semantics when it comes to returning Python objects from a C function.

The limited examples in the Python docs usually show a C function which returns the result of Py_BuildValue. Now, Py_BuildValue returns a New Reference, and transfers ownership of this reference over to the interpreter. So, can I extrapolate from this that it is a general rule that any object returned to Python must be a new reference, and that returning an object from a C function is the same as transferring ownership of the object over to the interpreter?

If so, what about cases where you return an object that is already owned by something? For example, suppose you write a C function which takes in a PyObject* which is a tuple, and you call PyTuple_GetItem on it and return the result. PyTuple_GetItem returns a borrowed reference - meaning that the item is still "owned" by the tuple. So, does a C function which returns the result of something like PyTuple_GetItem have to INCREF the result before returning it to the interpreter?

For example:

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?
}

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(1

下雨或天晴 2024-11-17 08:14:24

Python 期望您暴露给它的任何函数都返回一个引用,是的。如果您只有借用的引用,则必须调用 Py_INCREF 来提供新的引用。如果您返回借用的引用,Python 将继续调用 Py_DECREF(当引用完成时),最终将导致对象在仍在使用时被释放。

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

Python expects any function you expose to it to return a new reference, yes. If you only have a borrowed reference, you have to call Py_INCREF to give a new reference. If you return a borrowed reference, Python will proceed to call Py_DECREF (when it's done with the reference), and eventually that will cause the object to be freed while it is still in use.

(It's not uncommon for that "eventual" freeing to happen during interpreter exit, in which case it may go unnoticed, but it's still a mistake to return borrowed references.)

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文