2011-12-16 99 views
11

我正在爲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_SetItemPyList_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); 

我說得對不對?

+0

這個問題似乎涉及:http://stackoverflow.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

回答

3

如果您查看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