Sorry if this actually made it through the first time, I've looked on the archives and don't see it. I've joined the mailing list now, so maybe that's a necessary prerequisite for posting.
Begin forwarded message:
I've been using SIP successfully for over a year, and it's a great product!
I'm upgrading from 4.7.9 to 4.10.3 (well .4 now) and ran into a problem I had to work around and wanted to see if it's actually a bug.
I have a class like this:
class OuterClass { public: struct Inner { int x; };
OuterClass() ~OuterClass() Inner inner; };
With the default SIP wrapper, I can do this:
o = OuterClass() i = o.inner del o # actually causes the delete of outer (and inner)! print i.x # accesses deleted cpp object
I was able to fix it by taking advantage of the ->user member, but I'll have to do this for every struct/class that is a member variable in a class.
class OuterClass { %TypeHeaderCode #include "tester.h" %End public: struct Inner { int x; }; OuterClass(); ~OuterClass(); Inner inner; %GetCode sipPy = sipConvertFromType(&sipCpp->inner,sipType_OuterClass_Inner, NULL);
// if user is not null, we got an already created sipPy with the // user pointer already set to the containing class if (((sipSimpleWrapper *)sipPy)->user == NULL) { PyObject *outerPy = sipConvertFromType(sipCpp,sipType_OuterClass, NULL); ((sipSimpleWrapper *)sipPy)->user = outerPy; } %End };
This takes advantage of the fact that getting the OuterClass python object increments the refcount on it, and that deallocing the inner class automatically decrefs the user python object. It works even if you grab multiple references to the inner member variable and deletes outer when the last inner reference is deleted.
It might make more sense to fix it by using the extra_refs, but it wasn't as accessible from the sip file.
Let me know what you think.
Enclosed is the test code. You can see the problem if you comment out the %GetCode section.
|
tester.sip
Description: Binary data
import fun
print "Create outer class"
outer = fun.OuterClass()
print "Get reference to inner class"
inner = outer.inner
inner2 = outer.inner
print "Access inner class reference"
print inner.x
print "Delete outer class"
del outer
print "Access inner class reference"
print inner.x
print "delete inner class"
del inner
print "Access inner2 class reference"
print inner2.x
print "delete inner2 class"
del inner2
print "done"
tester.h
Description: Binary data
from distutils.core import setup, Extension
import sipdistutils
setup(
name = 'fun',
version = '1.0',
ext_modules=[
Extension("fun", ["tester.sip"],
include_dirs=['.']),
],
cmdclass = {'build_ext': sipdistutils.build_ext}
)
_______________________________________________
PyQt mailing list [email protected]
http://www.riverbankcomputing.com/mailman/listinfo/pyqt