[Pyrex] C++ object construction/destruction
Joel B. Mohler
joel at kiwistrawberry.us
Wed Jun 20 14:40:52 UTC 2007
Here's a bit of a trick which I think might be of interest to people who wish
to use C++ from pyrex. I apologize to the pyrex list if this is already
amply covered (I was unable to find searchable mailing list archives to
search for my possible redundancy.)
Here's the situation. I have a C++ class (I'll call it Foo) which I want to
wrap for access from python. I have a choice. I can initialize a pointer to
my object in the __new__ function in my python/pyrex object and delete in the
__dealloc__ or I can simply declare the object as member of the pyrex cdef'ed
class (not a pointer so as to save yourself a memory allocation):
cdef class FooWrapper:
cdef Foo x
This seems to work just fine ... as long as the constructor of Foo isn't too
exciting. However, there's a very bad problem. Neither the constructor or
destructor are called for Foo since the memory is allocated with malloc (or
PyMalloc or something). So, you need to call the constructor and destructor
somehow. The rest of this e-mail provides a simple way to do so. Thanks to
David Harvey for pointing out this matter and helping with the solution even
though I was comforted by the fact that my code worked -- actually, in my
situation, I had a memory leak since the destructor wasn't called!
Here's a link to a little C++ header file which declares 4 templated functions
which call C++ constructors and destructors both with and with-out
allocating/deallocating memory.
http://sage.math.washington.edu/home/jbmohler/patches/ccobject.h
The main trick is that we need to call the constructor of Foo, but the memory
is already allocated. An important nuance of the C++ new operator is
described here:
http://publib.boulder.ibm.com/infocenter/macxhelp/v6v81/index.jsp?topic=/com.ibm.vacpp6m.doc/language/ref/clrc05cplr199.htm
Declare these for pyrex:
#### foo.pxd
cdef extern from "foo.h":
ctypedef struct Foo:
pass
# Some non-allocating versions
Foo* Foo_construct "Construct<Foo>"(void *mem)
void Foo_destruct "Destruct<Foo>"(Foo *mem)
# some allocating versions for completeness
Foo* Foo_new "New<Foo>"()
void Foo_delete "Delete<Foo>"(Foo *mem)
### foo.pyx
cdef class FooWrapper:
def __new__(self):
Foo_construct(&self.x)
def __dealloc__(self):
Foo_destruct(&self.x)
--
Joel
P.S. To the sage list, this implementation is already substantially complete
for the wrapper for NTL.
More information about the Pyrex
mailing list