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.

Attachment: 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"

Attachment: 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}
)

Brian Olson
719-522-2808




_______________________________________________
PyQt mailing list    [email protected]
http://www.riverbankcomputing.com/mailman/listinfo/pyqt

Reply via email to