[C++-sig] Re: keeping weak_ptrs upon python objects smart_ptr holders

David Abrahams dave at boost-consulting.com
Wed Nov 19 23:38:32 CET 2003


"Nicolas LELONG" <nico_ml at mgdesign.org> writes:

> Hi everyone,
>
> I've been trying to wrap my Observer pattern implementation with
> BPL. I'm willing to be able to create new observers in Python.  My
> listeners objects keep weak_ptrs upon their observers, these
> weak_ptrs are used to notify the observers and to be able to know if
> a given observer is still "alive".
>
> I have not been able to obtain a weak_ptr that references the real
> shared_ptr holding the observer objects. The weak_ptrs I get seem to
> reference a dummy smart_ptr which is destoyed after the execution of
> python::detail::caller_arity<>::impl<>::operator().

It's not a dummy, but it is conjured up "from thin air" using a custom
deleter which just manages a reference to the containing Python
object.  If you don't copy this into some other shared_ptr somewhere,
it becomes the last one using that count after the call completes.

If you change the way A is wrapped so it's held by shared_ptr:

   class_<A,boost::shared_ptr<ACallback>, boost::noncopyable>("A")
       ...
       ;


and change:

   setInstance(boost::shared_ptr<A> a) { instance = a; };

to

   setInstance(boost::shared_ptr<ACallback>& a) { instance = a; };

*then* the weak pointer will be using the shared_ptr inside the
Python object.   I think it might be better to do more to make this
work automatically, but I'm not sure just what that "more" would be.

> The 'problem' can be seen with the following code :
>
> **** c++ code **********************************************
>
> struct A
> {
>     virtual ~A(){}
>     virtual std::string f() = 0;
> };
>
> struct ACallback :  A,  Callback
> {
>     ACallback (PyObject* self) : Callback(self) {}
>
>     std::string f()
>     {
>       object self(handle<>(borrowed(mSelf)));
>       return extract<std::string>(self.attr("f")());
>     }
> };
>
> boost::weak_ptr<A> instance;
>
> void setInstance(boost::shared_ptr<A> a) { instance = a; };
>
> std::string doInstance()
> {
>   boost::shared_ptr<A> a = instance.lock();
>   if (a.get() == NULL)
>     return "no more object here!";
>   else
>     return a->f();
> };
>
> BOOST_PYTHON_MODULE( test )
> {
>   class_<A, ACallback, boost::noncopyable>("A")
>     .def("f", pure_virtual(&A::f));
>
>   def("setInstance", setInstance);
>   def("doInstance", doInstance);
> }
>
> ******** python script ***************************
>
> from test import *
>
> class E(A):
>   def f(self):
>     return 'E::f'
>
> e = E()
> setInstance(e)
> res0 = doInstance()
> res1 = e.f()
>
> ***************************************************
>
> At the end of the script, res0 contains 'no more object here!' and res1
> contains what I'd like res0 to contain : 'E::f' !
>
> I did not find any information that could help me to solve this problem.
> Is there any known way to achieve this or am I doomed to get rid of
> weak_ptrs ?!
>
> Thanks,
> Nicolas.

-- 
Dave Abrahams
Boost Consulting
www.boost-consulting.com





More information about the Cplusplus-sig mailing list