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
> 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
> think that makes a lot of difference. The multiple references (to
> 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
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.
> only done a couple of those - QStringList is one example, I believe
> code that I borrow from). Look at qt/qstringlist.sip in PyQt.
> 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