On Aug 27, 2009, at 11:24 AM, Alexey Shamrin wrote: > Hello! > > I am wrapping an open source library with Cython. Hope to release some > code soon... > > First of all, Cython works great for this! It took some time to get > used to, but soon it became fun to work on a C-Python border! :-) > > And now the question. > > The C library has structures that I'm wrapping with extension types. > Here's the code (simplified and without error handling): > > cdef extern from "library.h": > ctypedef struct lib_obj: > int n > > int allocate_obj(lib_obj **obj) > void deallocate_obj(lib_obj *obj) > > cdef class Object(object): > cdef lib_obj *obj > > def __cinit__(self, n): > allocate_obj(&self.obj) > self.obj.n = n > > def __dealloc__(self): > if self.obj: > deallocate_obj(self.obj) > > Everything is nice so far. But then I had to wrap two more functions > from "library.h": > > cdef extern from "library.h": > ... > # these functions transfer deallocation responsibility to the > caller > int copy_obj(lib_obj **dst, lib_obj *src) > lib_obj *load_some_obj() > > As you can see, I needed to create Object instances not only from > scratch, but reusing existing lib_obj pointer and skipping memory > allocation. Plus a nice copy_obj wrapper. After some trial-and-error > the code became: > > cdef class Object(object): > cdef lib_obj *obj > > def __cinit__(self, n=None, allocate=True): > if allocate: > allocate_obj(&self.obj) > self.obj.n = n > > def __dealloc__(self): > if self.obj: > deallocate_obj(self.obj) > > def copy(self): > cdef lib_obj *obj > copy_obj(&obj, self.obj) > o = Object(allocate=False) > o.obj = obj > return o > > cdef Object wrap(lib_obj *obj): > Object o > o = Object(allocate=False) > o.obj = obj > return obj > > def load_Object(): > cdef lib_obj *obj = load_some_obj() > return wrap(obj) > > Well, it works ;-) But can you suggest a nicer way to accomplish > this? Problems: > > 1. Now I have to handle __cinit__ `allocate` argument in every > `Object` subclass. It's easy to forget about it -- I'm writing many > such subclasses.
I don't see how you'd get around this--somewhere you have to give that information to the __cinit__ method. Does each subclass have to do something extra in __cinit__? It could be wasteful, but the logic might be simpler to either always assume it's allocated and deallocate in copy and wrap. I don't know what you're doing with these things, but if you never wrap None you could use n=None as a sentinel to not allocate, only allocating if you're actually wrapping something. It's really hard to tell without understanding how it's going to be used. > 2. Notice how I forgot to check for `n` value in __cinit__. One more > thing to forget... > 3. I couldn't make `wrap` function a part of `Object` definition. I > tried to make it a cdef `fromobj` method decorated with @classmethod > or @staticmethod, but it didn't work. cdef methods can't (yet) have decorators like this, but a module- level function should work fine. - Robert _______________________________________________ Cython-dev mailing list [email protected] http://codespeak.net/mailman/listinfo/cython-dev
