[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