Closed
Description
If I create a cdef
'd class in a cython file having a struct as class member, and then instantiate that class in python, the structs do not get destroyed when the python object is deleted. Adding an explicit call to the struct destructor in __dealloc__
will do the job however.
Example:
cppheader.hpp:
#include <vector>
typedef struct MyObject {
int val;
std::vector<double> big_obj;
} MyObject;
typedef struct InfoHolder {
std::vector<MyObject> v;
int some_val;
} InfoHolder;
void increase_size(MyObject &my_obj)
{
my_obj.big_obj.resize(10000000, 1);
}
void force_destroy(InfoHolder &info_holder)
{
info_holder.~InfoHolder();
}
cyfile.pyx:
from libcpp.vector cimport vector
cdef extern from "cppheader.hpp":
ctypedef struct MyObject:
int val
vector[double] big_obj
ctypedef struct InfoHolder:
vector[MyObject] v
int some_val
void increase_size(MyObject &my_obj)
void force_destroy(InfoHolder &info_holder)
cdef class PyInfoHolder:
cdef InfoHolder info_holder
def __init__(self):
self.info_holder.v.resize(1);
increase_size(self.info_holder.v.at(0))
def say_hello(self):
print("hello")
pyfile.py:
from cyfile import PyInfoHolder
for i in range(100):
py_obj = PyInfoHolder()
py_obj.say_hello()
print("end")
Watch the memory usage when running python pyfile.py
, and then compare against the following alternative cython class:
cdef class PyInfoHolder:
cdef InfoHolder info_holder
def __init__(self):
self.info_holder.v.resize(1);
increase_size(self.info_holder.v.at(0))
def __dealloc__(self):
force_destroy(self.info_holder)
def say_hello(self):
print("hello")
(For some reason, the structs also cannot call their destructor explicitly within cython - e.g. self.info_holder.~InfoHolder()
fails to compile)