I have some code that is using PyDict internally to store data. A user sets the data like you would with a normal python dictionary, and the data is stored by the C code in the PyDict object. My question is this: Do I need to reference count (Py_INCREF) the value AND the key? Just the value? The documentation indicates that calling PyDict_SetItem does NOT steal a reference for the value. My understanding is that this means the PyDict object is not responsible for the value PyObject, so the reference count needs to be incremented. No mention is made of the key in the docs - does it need to be incremented as well?
A related question involves the deallocator for my code - these reference counts need to be cleaned up - is there any "short cut" to iterate on iterables in the C API and decrement all references, or will I need to manually iterate on the PyDict object and decrement all the values individually (and possibly the keys, depending on the response to the above?)
The code in question would look something like this (with questions in the comments):
int myobject_setitem(myobject *self, PyObject *key, PyObject *value) {
if (value) {
Py_INCREF(key); // <--- is this needed?
Py_INCREF(value);
return PyDict_SetItem(self->data, key, value);
}
/* I assume I need to look up the value so I can decrement the reference count
before removing it from the dictionary, right? */
PyObject *value = PyDict_GetItem(self->data, key);
if (!value) {
return -1;
}
int ret = PyDict_DelItem(self->data, key);
Py_DECREF(key); // <------- is this needed?
Py_DECREF(value);
return ret;
}
As far as the destructor/deallocator, I assume I'd just have to iterate on the dict manually and decrement the values (and maybe keys?) unless there is a better way? (To be clear I mean in the tp_dealloc function)
You do not need to perform any reference count handling here. The dict owns all references it holds, and it will manage the incref/decref calls. You do not own any of the references being created or destroyed. You also do not need to call PyDict_GetItem.
The same goes for your deallocator. You only own the reference to the dict itself, not the dict's references to its contents. You only need to decref the dict. The dict will handle its contents.