pythonpython-c-apipython-c-extension

Is it necessary to destuct a c-class in the python-c-api destuction function?


I have defined a python-c-api class, its real data structure is as follow:

typedef struct _C_CMISS_h
{
    PyObject_HEAD             // == PyObject ob_base;
    TestClass _in_Handle;
}C_CMISS_h;

Here is the destruction function, every time the python class is destructed, this function would be processed.

static void C_CMISS_Destruct(C_CMISS_h* Self){ //reload the destuction method
    /*Self->_in_Handle.~TestClass(); //destruct the C class*/
    Py_TYPE(Self)->tp_free((PyObject*)Self); //destruct this instance
} 

Is it necessary to let this function destruct the C class? Maybe when destructing the python object, Self could be deleted in the memory, therefore, the _in_Handle would call the C destruction method automaticly. However, if _in_Handle would not be deleted, this destruction method would not be processed. Because the destruction method should not be called by twice or more times, I want to know whether it is necessary to call it artificially.


Solution

  • Yes, it is necessary to call the destruction function artificially.

    In this example, if we define the destruction method of Testclass as:

    .cpp

    TestClass::~TestClass(){
        cout << "CALL THE DESTRUCTION!!!!" << endl;
    }
    

    Then we do not call it in the destruction function of the PyClass which name is cclass. After that, write a .py like this:

    .py

    import Xdll
    if __name__=='__main__':
        X = Xdll.cclass()
        print(X)
        X = 11
        print(X)
    

    You will find that you could not receive the message from the destruction method of TestClass. In fact, if you do not define this method artificially, the C class would remain in the memory and take the memory space. Compare to this method:

    typedef struct _C_CMISS_h{
        PyObject_HEAD
        TestClass _in_Handle;
    }C_CMISS_h;
    

    Using this method to define the data region is recommended:

    typedef struct _C_CMISS_h{
        PyObject_HEAD
        TestClass *_in_Handle;
    }C_CMISS_h;
    

    Then you could use new and delete to controll your memory space artificially.