On Thu, Jul 23, 2009 at 8:28 PM, Robert
Bradshaw<[email protected]> wrote:
> On Jul 23, 2009, at 12:10 PM, Lisandro Dalcin wrote:
>
>> On Thu, Jul 23, 2009 at 10:29 AM, Richard
>> Clarke<[email protected]> 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
>> [email protected]
>> http://codespeak.net/mailman/listinfo/cython-dev
>
> _______________________________________________
> Cython-dev mailing list
> [email protected]
> http://codespeak.net/mailman/listinfo/cython-dev
>
_______________________________________________
Cython-dev mailing list
[email protected]
http://codespeak.net/mailman/listinfo/cython-dev