I'm just trying to understand how to deal with the reference counts when using the Python C API.
I want to call a Python function in C++, like this:
PyObject* script;
PyObject* scriptRun;
PyObject* scriptResult;
// import module
script = PyImport_ImportModule("pythonScript");
// get function objects
scriptRun = PyObject_GetAttrString(script, "run");
// call function without/empty arguments
scriptResult = PyObject_CallFunctionObjArgs(scriptRun, NULL);
if (scriptResult == NULL)
cout << "scriptResult = null" << endl;
else
cout << "scriptResult != null" << endl;
cout << "print reference count: " << scriptResult->ob_refcnt << endl;
The Python code in pythonScript.py is very simple:
def run():
return 1
The documentation of "PyObject_CallFunctionObjArgs" says that you get a new reference as return value. So I would expect "scriptResult" to have a reference count of 1. However the output is:
scriptResult != null
print reference count: 72
Furthermore I would expect a memory leak if I would do this in a loop without decreasing the reference count. However this seems not to happen.
Could someone help me understand?
Kind regards!
ecatmur is right, numbers and strings are interned in Python, so instead you can try with a simple object()
object.
A simple demo with gc
:
import gc
def run():
return 1
s = run()
print len(gc.get_referrers(s)) # prints a rather big number, 41 in my case
obj = object()
print len(gc.get_referrers(obj)) # prints 1
lst = [obj]
print len(gc.get_referrers(obj)) # prints 2
lst = []
print len(gc.get_referrers(obj)) # prints 1 again
A bit more: when CPython creates a new object, it calls a C macro _Py_NewReference
to initialize the reference count to 1. Then uses Py_INCREF(op)
and Py_DECREF(op)
to increase and decrease the reference count.