[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