Python C扩展中的引用计数
问题描述:
我正在为Python编写我的第一个C扩展,并对引用计数感到困惑。这是我想要做的。Python C扩展中的引用计数
我填充字典的for循环:
mydict = PyDict_New();
for (...)
{
pair = PyTuple_Pack(2, PyString_FromString("some string"),
PyString_FromString("some other string"));
/* at this point, the refcnt for the tuple is 1, the refcnts for the
2 string items are 2. Because according to the source, PyString_FromString
does an INCREF, and PyTuple_Pack() does an INCREF on its items
*/
PyDict_SetItem(mydict, PyString_FromString("some key"), pair);
/* At this point, the key's refcnt is 2. PyString_FromString sets it to 1 and
PyDict_SetItem INCREF's it. Ditto for pair since PyDict_SetItem also INCREF's
the value.
*/
Py_DECREF(pair);
/* pair's refcnt is 1 which makes sense to me since mydict now owns the tuple,
but the refcnt for its items are still at 2. I don't understand this part.
*/
}
return mydict;
是我裁判计数是否正确?在C API文档中,它特别建议使用PyObject_FromXXX
函数作为PyTuple_SetItem
或PyList_SetItem
的参数,因为它们“窃取”引用。
没有记录PyDict_SetItem
是否盗取了引用。我猜它不会在这种情况下, 我应该做的
first = PyString_FromString("some string");
second = PyString_FromString("some other string");
pair = PyTuple_Pack(2, first, second);
Py_DECREF(second);
Py_DECREF(first);
我说得对不对?
答
如果您查看PyTuple_Pack的CPython源代码(Objects/tupleobject.c),您会发现它的确会增加每个打包对象的引用计数。如果您改为执行PyTuple_New,然后执行PyTuple_SetItem调用,您将不需要减少引用计数,因为SetItem会窃取引用。最后,你可能只想使用Py_BuildValue(“(ss)”,“some string”,“some other string”); 它将建立自己的元组你,它会为你创建PyStrings: http://docs.python.org/c-api/arg.html#Py_BuildValue
这个问题似乎涉及:http://*.com/questions/6977161/where-should-i-put-py-incref-和py-decref-on-this-block-in-python-c-extension – Daenyth 2011-12-16 00:38:44