On Thu, Jul 23, 2009 at 8:28 PM, Robert Bradshaw<rober...@math.washington.edu> wrote: > On Jul 23, 2009, at 12:10 PM, Lisandro Dalcin wrote: > >> On Thu, Jul 23, 2009 at 10:29 AM, Richard >> Clarke<rscla...@gmail.com> wrote: >>> Thank you Robert, the explanation on how and where to use cdef was >>> most helpful. I think it has just clicked(with a flag waving >>> 'idiot'). >>> >>> The PyCObject concept is a nice idea, removing cdef foo_t *foo from >>> outside of __init__ ? However, I see implications in memory >>> deallocation. How does cython currently handle memory deallocation? >> >> I'm not sure you need PyCObject for your code ... > > For sure PyCObject is not needed here. I was musing about a ptr <-> > object conversion happening automatically via PyCObject, just as we > handle the more basic numeric types. Deallocation of pointers needs > to be handled by the user explicitly, so perhaps it's not a good idea > to make this transparently easy. > >> >>> >>> I assume the best practice would be for users to deallocate memory in >>> the class __del__ method (calling the appropriate wrapped c library >>> destructor). >> >> Yes. More specifically, you should allocate stuff in __cinit__(), and >> deallocate stuff in __dealloc__()... > > +1. To clarify, __cinit__ is called exactly once per object creation > (no such guarantee with __init__). Likewise, __dealloc__ is always > called exactly once upon collection. This makes memory management > easy--essentially you're boostrapping of Python's refcounting. > >> >> >>> Otherwise does cython simply free(foo) or interprets the >>> language to build a depth first deallocation method? >> >> Cython does not manage memory allocated with malloc()... you have to >> manage deallocation yourself... >> >> >>> I guess it >>> should do the simplest free(foo), if the developer was lazy not to >>> deallocate memory, they can suffer with memory leaks. I think I >>> might >>> have answered my own question here... >>> >> >> In short, you have to modify your class, using something like this >> >> cdef class Bar: # NOTE: "cdef" class >> >> cdef foo_t *c_foo # NOTE: "cdef" instance (not class) member!!! >> >> def __cinit__(self): # NOTE: using "__cinit__", not "__init__" >> self.c_foo = self.c_open() >> >> def __dealloc__(self): # NOTE: using "__dealloc__", not "__del__" >> if self.c_foo != NULL: >> free(self.c_foo) >> >> cdef foo_t* c_open(self): # NOTE: using "cdef", not "def", this >> method will not show-up on Python side, it is a kind of internal, >> private method. >> cdef foo_t *foo = NULL >> foo = init() >> return foo >>
I'm not sure if this is the correct way (it appears to work) but here goes... If we consider Bar to be the encapsulating class for the foo_t struct, in my case I need access to this foo_t struct in other classes. Using Lisandro's Bar class as above with an extra method, class Qux demonstrates how to obtain the foo_t pointer. This in turn could be passed in to other c library function calls etc. // foo.pyx cdef extern from "stdlib.h": ctypedef unsigned long size_t void free(void *ptr) cdef extern from "foo.h": ctypedef struct foo_t: int fd foo_t* init() cdef class Bar: cdef foo_t *foo def __cinit__(self): self.foo = self.__open() self.foo.fd = 1 def __dealloc__(self): if self.foo != NULL: free(self.foo) cdef foo_t* __open(self): cdef foo_t *f f = init() return f cdef foo_t* get_foo(self): return self.foo class Qux: def __init__(self): global qux qux = Bar() def something(self): cdef foo_t* _foo _foo = Bar.get_foo(qux) if _foo != NULL: #Do something with the struct Thanks to both of you for your help, Richard. >> >> -- >> Lisandro Dalcín >> --------------- >> Centro Internacional de Métodos Computacionales en Ingeniería (CIMEC) >> Instituto de Desarrollo Tecnológico para la Industria Química (INTEC) >> Consejo Nacional de Investigaciones Científicas y Técnicas (CONICET) >> PTLC - Güemes 3450, (3000) Santa Fe, Argentina >> Tel/Fax: +54-(0)342-451.1594 >> _______________________________________________ >> Cython-dev mailing list >> Cython-dev@codespeak.net >> http://codespeak.net/mailman/listinfo/cython-dev > > _______________________________________________ > Cython-dev mailing list > Cython-dev@codespeak.net > http://codespeak.net/mailman/listinfo/cython-dev > _______________________________________________ Cython-dev mailing list Cython-dev@codespeak.net http://codespeak.net/mailman/listinfo/cython-dev