2011-12-16 18 views
11

私は最初のCエクステンションをPythonに書いていますが、リファレンスカウントについて混乱しています。ここに私がやろうとしていることがあります。Python Cエクステンションのリファレンスカウント

私はループの中に辞書を移入:

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

を行う必要はありません推測していますか?

+0

この質問は関連すると思われます:http://stackoverflow.com/questions/6977161/where-should-i-put-py-incref- py-decref-on-block-in-python-c-extension – Daenyth

+0

関連はありますが重複しない:PyTuple対PyDict – gecco

答えて

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

関連する問題