[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