Pergunta

I am lost on Py_DECREF/INCREF when handling PyList_Append. Can anybody have comments on the following codes?

PyObject * bugmaybe(PyObject *self, PyObject *args)
{
   PyObject * trio=PyList_New(0);
   PyObject * trio_tmp;
   PyObject * otmp = PyFloat_FromDouble(1.2);
   PyList_Append(trio_tmp,otmp);
   //Py_DECREF(otmp);
   otmp = PyFloat_FromDouble(2.3);
   PyList_Append(trio_tmp,otmp);
   //Py_DECREF(otmp);
   PyList_Append(trio,trio_tmp);
   Py_INCREF(trio_tmp);
}
Foi útil?

Solução

If you know the size of the list upfront its usually faster to create the list with the right size and use PyList_SetItem().

Your code is simply wrong, trio_tmpis uninitialized.

Try this:

PyObject * bugmaybe(PyObject *self, PyObject *args)
{
  PyObject * trio=PyList_New(3);
  PyObject * otmp = PyFloat_FromDouble(1.2);
  PyList_SetItem(trio,0,otmp);
  otmp = PyFloat_FromDouble(2.3);
  PyList_SetItem(trio,1,otmp);
  PyList_Append(trio,2, PyList_New(0));
  return trio;
}

If you really want to use PyList_Append, your code was mostly ok, just missing the initialization for trio_tmpand the superfluous Py_INCREF at the end.

PyObject * bugmaybe(PyObject *self, PyObject *args)
{
  PyObject * trio=PyList_New(0);
  // trio has refcount 1
  PyObject * trio_tmp = PyList_New(0);
  // trio_tmp has recount 1
  PyObject * otmp = PyFloat_FromDouble(1.2);
  // otmp has recount 1
  PyList_Append(trio_tmp,otmp);
  // Append does not steal a reference, so otmp refcoun = 2
  Py_DECREF(otmp);
  // otmp refcount = 1, but stored in the list so the pointer var
  // can be reused
  otmp = PyFloat_FromDouble(2.3);
  PyList_Append(trio_tmp,otmp);
  Py_DECREF(otmp);
  // as above
  PyList_Append(trio,trio_tmp);
  // decrement refcount for trio_tmp, as it has recount 2 now.
  Py_DECREF(trio_tmp);
  return trio;
}

The code above would be equivalent to:

 trio = []
 trio_tmp = []
 otmp = 1.2
 trio_tmp.append(otmp)
 otmp = 2.3
 trio_tmp.append(otmp)
 trio.append(trio_tmp)

Hope it helps. The main hint is in the docs, if it says 'Steals a reference' then the function basically takes ownership, if it says 'New Reference' then it did an INCREF for you, if nothing is said it probably does an INCREF and DECREF pair as needed.

Outras dicas

PyList_Append() does not "steal" a reference, therefore if you are not going to use the appended value after, decref it.

Also, don't forget to return a PyObject* from the function or the system will think that an exception has occurred.

Licenciado em: CC-BY-SA com atribuição
Não afiliado a StackOverflow
scroll top