[PyKDE] boost::shared_ptr

Jim Bublitz jbublitz at nwinternet.com
Tue Mar 22 20:34:10 GMT 2005


On Tuesday 22 March 2005 10:04, James Emerton wrote:
> On 22-Mar-05, at 12:23 AM, Jim Bublitz wrote:
> <snip>
>
> > It seems to me Python is taking care of all of the ref counting in
> > this case -
> > there might be pathological cases where either the C++ instance of the
> > template type or the Python instance get orphaned (no corresponding
> > object on
> > "the other side"). Most PyKDE programs don't use these types very much
> > explicitly (although the little testing I've done hasn't shown any
> > problems
> > yet).
> > Allocating new objects in each conversion function seems to bypass the
> > C++ ref
> > counting feature. There's a new C++ object created each time, but I
> > don't
> > think that makes a lot of difference. The multiple references (to
> > Python
> > objects) on the Python side will be managed by Python
>
> It appears that when passing Python instances back into C++ you are
> creating a second, unrelated smart pointer.  Unless KSharedPtr is
> maintaining a mapping of C++ pointers, the pointer that gets passed in
> is getting an extra reference added to it that will never go away.
> When the pointer is passed back out of Python, you area creating an
> unassociated smart pointer that will deallocate the contained pointer
> when it goes out of scope, potentially leaving a dangling pointer.

Yeah - I forgot about that part (or ignorant of it - not sure which). The 
problem is that incrementing the ref count of the original pointer (sipCpp) 
has the same result, and the underlying object doesn't have a copy 
constructor (I believe boost works that way too).

In the PyKDE case that isn't a big problem, since the code that uses smart 
pointers isn't used often from Python. Probably will fix it eventually.

> My current approach is to create a small inline class in the
> %TypeHeaderCode and use SIP to wrap the inline class.  This works
> wonderfully, and doesn't require any especially wacky code.  =)

> Problem is, I also have places where I would like to reimplement an
> interface in Python and pass an instance back into C++ as a smart
> pointer.  The inline wrapper class defeats this, of course.

> I am considering some sort of hack involving a %MappedType and a map<
> T*, boost::shared_ptr<T> >  When I convert a C++ smart pointer into a
> Python type, I stick the row pointer and its corresponding smart
> pointer into a map.  This holds a reference and protects the pointer.
> I also add some %MethodCode to the destructor that pulls the element
> out of the map, rather than deleting the pointer directly.  The theory
> sounds pretty good, I hope it holds up in practice.

It seems like you should be able to subclass the shared ptr and bind the 
subclass instead, overload the C++ dtor to Py_DECREF the corresponding Python 
object (need to keep a ptr to it) and overload __del__ to decrement the ref 
count of the C++ object.

Jim




More information about the PyQt mailing list