从C返回对象到Python [英] Returning objects to Python from C

查看:71
本文介绍了从C返回对象到Python的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

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

Python文档中的有限示例通常显示一个C函数,该函数返回Py_BuildValue的结果.现在,Py_BuildValue返回一个New Reference,并将此引用的所有权转移到解释器.因此,我可以据此推断出,这是一条通用规则,即返回给Python的任何对象都必须是一个 new引用,并且从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?
}

解决方案

Python希望您公开给它的任何函数都返回 new 引用,是的.如果您只有借用的参考,则必须调用Py_INCREF来提供新的参考.如果您返回借用的引用,Python将继续调用Py_DECREF(在完成引用后),最终这将导致该对象在仍在使用时被释放.

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

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

解决方案

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.)

这篇关于从C返回对象到Python的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆