[C++-sig] storing weak_ptr to this in classes extended from python

Jim Bosch talljimbo at gmail.com
Sat Feb 4 17:40:54 CET 2012


On 02/03/2012 02:26 PM, Holger Brandsmeier wrote:
> Dear list,
>
> Note: I am actually using Teuchos::RCP instead of boost::shared_ptr
> and boost::weak_ptr, but I already mirrored almost all the special
> treatments in boost::python, and have been successfully using this for
> a while. Everything that I write should actually apply to both
> implementations in the same way.
>
> I have a class that needs to store an RCP to itself to pass it along
> to some classes that it creates, which might later need the RCP to
> keep the original class alive. In C++ I implemented this by switching
> the constructor to procted, and by having a static create() method
> like this:
>
>   static RCP<PfemSpaceT>  create(RCP<  MeshT>  mesh, Point<int, meshdim>
> pol_deg_default)
>   {
>     RCP<PfemSpaceT>  ret(new PfemSpaceT(mesh, pol_deg_default));
>
>     ret->setThisRCP(ret);
>     ret->init();
>
>     return ret;
>   }
>
> The function setThisRCP() stores the shared point as a weak pointer.
> When you call getThisRCP() the a strong RCP is returned from this weak
> RCP. This is what you want as otherwise the class will never be
> deleted.
>
> The problem starts now as the same class is extended from python. I
> mirror the same implementation in python as:
>
>   def __init__(self, mesh, pol_deg, cb_setDofEntity):
>     super(PfemSpaceStaticCond, self).__init__(mesh, pol_deg, False)
>
>     self.setThisRCP(self)
>     self.init()
>
> Now I get serious problems with this call:
>     self.setThisRCP(self)
>
> My understanding is, that the following happens:
>   1) the from-python converter creates an RCP with the use count of
> one and a custom deletor
> (boost::python::converter::shared_ptr_deleter).
>   2) the function setThisRCP gets called and stores a weak RCP
>   3) the control gets back to python and the use count of the RCP
> drops to zero. The custom deletor dereferences the use count in
> python.
>
> Later calls to getThisRCP() that turn the weak RCP into a strong RCP
> are then invalid. When python no longer references the class, it gets
> deleted. Some C++ parts that used the RCP from getThisRCP() work on a
> class that has been deleted and at some point the program crashes.
> (Here maybe if I would use boost the program would crash already
> earlier).
>
> Do you have an idea how I can use the thisRCP paradigm together with
> C++ classes that are extended from python?
>

It sounds like you need to ensure that instances created in Python 
always use an RCP holder (even Python subclasses).  I'd have thought 
passing RCP<Wrapper> as the holder template argument in the class_ 
definition would do that, but I'm not that familiar with how 
smart-pointer holders interact with wrapper classes.

The second part is that you'd need to make sure #1 is replaced by having 
Boost.Python look in the holder, find that it has an internal RCP, and 
use that instead of creating a new temporary one.  I know Boost.Python 
can do that with shared_ptr at least some of the time, so I assume 
you've set it up so that's possible with RCP too.  You might try having 
setThisRCP take a non-const reference to an RCP, so Boost.Python is 
forced to use an lvalue converter and hence a non-temporary RCP.

Good luck!

Jim


More information about the Cplusplus-sig mailing list