[PyKDE] boost::shared_ptr

James Emerton james at emdata.net
Tue Mar 22 18:04:50 GMT 2005

On 22-Mar-05, at 12:23 AM, Jim Bublitz wrote:
> 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.

> You can also do the same thing (more or less) with %MethodCode - I'm 
> not sure
> why either case would require every method in a class to have 
> %MethodCode. Do
> you have a short example of how it's being used that might require 
> that, or
> do the methods just require the template-based type (%MappedType will 
> handle
> that)?

My original thought was to use %MethodCode to handle the extra 
indirection required to call through the smart pointer.  Basically to 
hang onto a pointer to boost::shared_ptr<T> and manually implement all 
the methods in the API.  After working with this for a day, I am not 
sure it is a very good approach.

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 would be really nice if Phil would add some form of smart pointer 
support to SIP.  *hint hint*  =)   I may write something myself 
eventually, if I can figure out what it should look like.

> It's a different problem if the template type is used as a base class. 
> I've
> only done a couple of those - QStringList is one example, I believe 
> (Phil's
> code that I borrow from). Look at qt/qstringlist.sip in PyQt. 
> Basically,
> you'd ignore the base class in the sip code and add any methods 
> required from
> the base class yourself.

QStringList is shared like a smart pointer, but the sharing happens 
internally, behind the interface being wrapped.  The problem with smart 
pointers is that they are external wrappers that SIP needs to know 
about to handle correctly.


This is not my home; the cats just let me stay here.

More information about the PyQt mailing list