On 04/22/2012 03:42 PM, Holger Brandsmeier wrote:
Dear list,how is it possible to have a class in C++ that can be extended from python and that stores a weak_ptr to itself? The reason why I want to do this: - using a weak_ptr to itself does not introduce a memory leak. - from a C++-member of that class I can call other functions that expect a shared_ptr<>, in that case I convert the weak_ptr to a shared_ptr and all the memory management works nicely. The way I would suspect this to work is: struct I { void setThisRCP(boost::shared_ptr<I> ptr) { thisRCP = ptr; } boost::shared_ptr<I> getThisRCP() const { return thisRCP.lock(); } boost::weak_ptr<I> thisRCP; }; Then I export this class to C++ and in python I would do: class IDer(I): def __init__(self): I.__init__(self) self.setThisRCP(self) And I would suspect that I can use that class now in C++ and in particular calling getThisRCP() from C++ returns a valid shared pointer. However, immediately after the call of `self.setThisRCP(self)` the weak_ptr is already invalid and getThisRCP returns an shared pointer to Null (None in python). Attached to this message is a very simple example that demonstrates how this failes for the above implementation, the ouptu for the snipped: print '\ntestcase for thisRCP as from python extended class:' i = IDer() assert i.getThisRCP() is not None fails the assertion. However if I do the equivalent to IDer purely in C++ (which is not really an option) then everything works (see attachment) with the putput testcase for thisRCP as set from C++: 42 destructor for J called ... I suspect that the error comes from the fact that boost python create as temporary shared_ptr that is passes to setThisRCP() which is not the shared pointer that actually holds the instance of IDer in python (is it actually hold as a shared_ptr?). Do you have any proposal of how I can implement the above pattern with boost python? Or is this completly impossible at the moment?
I agree with your suspicion about what's going on here, though I haven't (yet) tested your example. One quick thing to try would be having setThisRCP() take a shared_ptr by reference - that should force Boost.Python to try to return the internal shared_ptr rather than create a temporary one.
Even if it fails, you may learn something about what's going on.
I also reported this issue before "storing weak_ptr to this in classes extended from python" but at that time I wasn't using shared_ptr and now I really suffer from the memory leak that was introduced by my workaround which was to store the thisRCP as a "shared_ptr" and I really need to fix that now. So here is a small little example that does not depend on any other parts of my library.
Thanks for the small example. Hopefully we can get to the bottom of this; you don't seem to be the only person who wants to do something like this.
Jim _______________________________________________ Cplusplus-sig mailing list [email protected] http://mail.python.org/mailman/listinfo/cplusplus-sig
