Search code examples
cython

Should the reference count of PyObject* created by a cdef public function be manually decreased


I want to export a python class to be used in C++:

class Object:
    def method(self):
        pass
    
cdef public object create_object() with gil:
    return Object()

cdef public void py_method(object obj) with gil:
    obj.method()  # obj is expected to have method()

Then the generated header file will have the following functions:

__PYX_EXTERN_C PyObject *create_object(void);
__PYX_EXTERN_C void py_method(PyObject *);

My question is: should I also have a function like

from cpython cimport Py_XDECREF, PyObject
cdef public void destroy_object(PyObject* obj) with gil:
    Py_XDECREF(obj)

to avoid memory leak?

Then these functions may be used in C++ code like:

auto obj = create_object()
py_method(obj)

// Finally
destroy_object(obj)

Solution

  • Yes you should decrement it when calling it from C++. You could do it the way you propose or you could skip the definition of destroy_object and just use Py_XDECREF in C++.

    Other things you should consider:

    • create_object can return NULL if it's raised a Python exception so check for that
    • RAII wrappers are always a good idea (to handle the reference counting)