[PyQt] SIP: how to transfer ownerships

Phil Thompson phil at riverbankcomputing.co.uk
Fri Oct 12 08:38:06 BST 2007


On Friday 12 October 2007, Martin Dobias wrote:
> Hi,
>
> I'm trying to find out how to wrap one class but I'm not sure how to
> do it correctly...
>
> I have a class which owns a geometry class. The geometry can be at
> some point of time detached from the class (and deleted elsewhere):
>
> class Feature
> {
> public:
>   [...]
>   // returns only reference
>   Geometry* getGeometry() { return geom; }
>   // marks that it's not responsible for geometry's deletion anymore
>   Geometry* getGeometryAndOwnership() { ownsGeometry = 0; return geom; }
>   // deletes the geometry if it's still owning it
>   ~Feature() { if (ownsGeometry) delete geom; }
> private:
>   bool ownsGeometry;
>   Geometry* geom;
> };
>
> My question is - what annotations should I use for the getter
> functions? I guess I should use TransferBack for
> getGeometryAndOwnership() as it takes the responsibility for deletion.

Correct. A better name for getGeometryAndOwnership() would be takeGeometry().

> But what about getGeometry() ? When used without any annotation I have
> a problem in this scenario:
> 1. feature is created
> 2. getGeometry is called and the reference is stored
> 3. feature is deleted
> 4. reference in python still exists but the object is deleted already...

I assume by "object" you mean a Geometry. You can't expect anything else to 
happen. The only question is whether or not the Python Geometry knows that 
the C++ Geometry exists. If it does know then you will get an exception if 
you try to use if, if not you will get a crash. Python will know if Geometry 
has a virtual dtor.

Alternatively you can provide %MethodCode for Feature's dtor that ensures that 
the Feature's Geometry will not get deleted if it is already wrapped. 
Something like...

~Feature()
%MethodCode
    // How do we know if the Geometry is valid?
    Geometry *geom = sipCpp->getGeometryAndOwnership();

    // The object returned owns the Geometry instance.
    PyObject *geom_obj = sipConvertFromInstance(geom, sipClass_Geometry,
            Py_None)

    // If the Geometry wasn't already wrapped then this will delete it.
    Py_XDECREF(geom_obj);
%End

The problem with this is that the Python and C++ dtors now have different 
semantics.

Phil


More information about the PyQt mailing list