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.


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.


James


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

_______________________________________________
PyKDE mailing list    PyKDE@mats.imk.fraunhofer.de
http://mats.imk.fraunhofer.de/mailman/listinfo/pykde

Reply via email to