[C++-sig] Re: problems with weak_ptr to python object

David Abrahams dave at boost-consulting.com
Tue Dec 14 21:52:14 CET 2004


Arthur Peters wrote:
> Hello,
> 
> I am working on a project that uses shared_ptr for more or less
> everything, so weak_ptrs are important. I discovered that the
> shared_ptrs created by boost.python from python objects that use
> shared_ptr as a holder are not shared_ptrs managing the same object as
> the holder, but are shared_ptrs managing a reference to the python
> object. This is fine until you make a weak_ptr to it. Then the weak_ptr
> will become invalid way before the actually object is destroyed.

Interesting.

The way to get at the underlying shared_ptr is to convert the Python
object to a non-const shared_ptr&.  So you could do:

template <class T>
weak_ptr<T> get_weak_ptr(shared_ptr<T> const& x)
{
    object python_owner(x);
    shared_ptr<T>& inner_shared_ptr(
          extract<shared_ptr<T>&>(python_owner));
    return inner_shared_ptr; // convert to weak_ptr.
};

> See the thread from a year ago called "keeping weak_ptrs upon python
> objects smart_ptrholders"
> (http://mail.python.org/pipermail/c++-sig/2003-November/006337.html).
> There was talk of fixing this problem. Did it go anywhere?

Was a solution proposed?  Oh, I see:

----schnipp------
wouldn't it be possible, when converting the arguments provided to a
function, that if :

- a shared_ptr (weak_ptr) argument is the 'target' of a specified implicit
conversion whose source is the type of
  the provided value for the argument

- AND the provided value wrapper is held by shared_ptr

- THEN the shared_ptr " conjured up 'from thin air' " is contructed from the
shared_ptr holding the provided value
  thus having a valid reference count

I don't if/where/how all this could be done, and if it covers every aspect
of the problem !
-----schnapp------

The problem is that the existing conversion has great value even when
the inner objects are held by shared_ptr.  If you're going to pass the
shared_ptr back to Python you should see the same managing object.
Otherwise you can end up with two different Python objects managing the
same C++ base sub-object <shiver>.

> I have had the following thoughts:
> 
> The problem is that a shared_ptr directly related (sharing a use_count)
> to the holder 

You lost me.  Which holder?

> is only passed to C++ if the type requested exactly
> matches the holder (I think). 


Example?

> And in other cases, a unrelated (seperate
> use_count) shared_ptr to the same object is passed.


> If a shared_ptr<void> was used in place of the void*s in the converter
> code the shared_ptr-ness could be preserved. It would be silly to use
> shared_ptr<void> when the target type was a plain pointer so maybe it
> would be possible to make a duplicate of a part of the "conversion
> path" that used shared_ptr<void>. This path could be used by
> shared_ptr_from_python to return shared_ptrs that are related to the
> shared_ptr that is the holder.
> 
> Does any of that make sense? I'm having trouble explaining my self.

No and yes ;-)

Give some code examples to show what you mean.

-- 
Dave Abrahams
Boost Consulting
http://www.boost-consulting.com




More information about the Cplusplus-sig mailing list