2011-12-16 11 views
11

Sto scrivendo la mia prima estensione C su Python e sono confuso circa i miei conteggi di riferimento. Ecco cosa sto cercando di fare.conteggi di riferimento in un'estensione Python C

Io popolo un dict in un ciclo 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; 

sono i miei conteggi ref corretta? Nei documenti API C, è consigliabile utilizzare le funzioni PyObject_FromXXX come argomenti su PyTuple_SetItem o PyList_SetItem perché "rubano" i riferimenti.

Non è documentato se PyDict_SetItem ruba i riferimenti. Sto indovinando non lo fa, nel qual caso, devo fare

first = PyString_FromString("some string"); 
second = PyString_FromString("some other string"); 
pair = PyTuple_Pack(2, first, second); 
Py_DECREF(second); 
Py_DECREF(first); 

ho ragione?

+0

Questa domanda sembra correlato: http://stackoverflow.com/questions/6977161/where-should-i-put-py-incref- e-py-decref-on-this-block-in-python-c-extension – Daenyth

+0

Correlati sì ma non duplicati: PyTuple vs PyDict – gecco

risposta

3

Se si guarda il codice sorgente CPython (Objects/tupleobject.c) per PyTuple_Pack, si noterà che effettivamente incrementa il conteggio dei riferimenti su ciascun oggetto imballato. Se invece si esegue un PyTuple_New seguito da chiamate PyTuple_SetItem, non sarà necessario decrementare i conteggi dei riferimenti poiché SetItem ruba i riferimenti.

Infine, si può semplicemente voler usare Py_BuildValue ("(ss)", "qualche stringa", "qualche altra stringa"); Sarà costruire il vostro tuple per voi e si creerà PyStrings per voi: http://docs.python.org/c-api/arg.html#Py_BuildValue