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

Reply via email to