I have a code in Python C API like this:
PyObject* result = PyObject_CallMethod(/* some function with some arguments */);
// Do something with result
Py_XDECREF(result);
I'm almost sure this code is fine from the point of view of references releasing when result is a PyObject* representing a simple type (PyBool, PyLong, PyFloat, etc.) but I'm unsure in the following cases:
- Dictionaries (i.e.
resultis ofPyDicttype) - Lists (i.e.
resultis ofPyListtype) - Text strings (i.e.
resultis ofPyUnicodeObjecttype)
(In case 1 and 2 my doubt is due to dictionaries/lists also use PyObject* for it's members and I'm not sure if Py_XDECREF() is smart enough to remove all references used internally in the dictionary/list or if I have to implement some kind of recursive removal function)
Is my approach right also for these types?
EDIT: to answer the question in the comment is the code you are using making references to the objects that are referenced by the dict or list? a closer version to reality is the following one.
As you can see, the processing of the result is done in a recursive way. Not sure if key, value and the result of PyList_GetItem(result, ix) are making references that should be freed in some way...
void process(PyObject* result) {
if (PyDict_Check(result)) {
PyObject *key, *value;
Py_ssize_t pos = 0;
while (PyDict_Next(value, &pos, &key, &value)) {
process(value);
}
} else if (PyList_Check(result)) {
Py_ssize_t size = PyList_Size(result);
for (Py_ssize_t ix = 0; ix < size; ++ix) {
process(PyList_GetItem(result, ix));
}
} else if (PyUnicode_Check(result)) {
const char* str = PyUnicode_AsUTF8(result);
// do something with str
} else {
// processing other types
}
// code entry point
PyObject* result = PyObject_CallMethod(/* some function with some arguments */);
process(result);
Py_XDECREF(result);