[PyQt] Conversion to wrong SubClass

Matthias Kuhn matthias at opengis.ch
Tue Jan 22 17:34:35 GMT 2019


On 1/22/19 10:04 AM, Phil Thompson wrote:
> On 21 Jan 2019, at 11:13 pm, Matthias Kuhn <matthias at opengis.ch> wrote:
>> Hi Phil
>>
>> On 1/18/19 2:13 PM, Phil Thompson wrote:
>>> On 18 Jan 2019, at 12:48 pm, Matthias Kuhn <matthias at opengis.ch> wrote:
>>>> Or does this mean that if the refcount for this Python object dropped to
>>>> 0 the cache will be invalidated anyway (and the real issue here is, that
>>>> the python object is still alive somewhere)?
>>> It should be invalidated when the ref count reaches 0.
>> It seems to be doing that. But when an additional /Transfer/ annotation
>> comes into play things start to go worse.
>>
>> The following code snippet reproduces the issue:
>>
>> https://issues.qgis.org/issues/20661#note-2
>>
>>
>> The interesting bits are the (almost) last two lines of the loop
>>
>> * pt_g.clone() is a /Factory/ method
>>
>> * The QgsGeometry constructor has a /Transfer/ annotation on the
>> parameter, if this one is not called, everything goes well.
>>
>>
>> Here are the first couple of lines of the output:
>>
>> ------------------------------------------
>>
>> new pt  0x5d98240
>> new pt  0x5f257c0
>> new pt  0x4283da0
>> new pt  0x5d98240
>> WHAT??????!!!!!  0x5f257c0
>> new pt  0x629fa60
>> new pt  0x5d3c470
>> WHAT??????!!!!!  0x5d98240
>> new pt  0x2e2ac90
>> new pt  0x4283da0
>> new pt  0x5dcef50
>> new pt  0x5f770d0
>> new pt  0x629fa60
>> WHAT??????!!!!!  0x5d98240
>>
>> ------------------------------------------
>>
>>
>> Any idea what the additional Transfer of the object triggers?
> See the docs.
>
> I can't really comment as you haven't explained the class hierachy or the use of annotations in the ctors.

To make it easier, I have extracted all the relevant information about
class hierarchy etc. here:

https://gist.github.com/m-kuhn/368c017f05183df707ce054c2f431830


The complete and complex version can be found here:

https://github.com/qgis/QGIS/tree/master/python/core/auto_generated/geometry

>
> Does the cloned object have a parent (in which case it's not a factory)?

There are no QObjects involved here.


My interpretation of what's going on:

* There's a `QgsGeometry` which owns a point `QgsPoint(QgsAbstractGeometry)`

* this point is cloned (ownership of the clone goes to Python at this
point) (/Factory/)

* the clone is then transferred to C++ by calling the `QgsGeomtery(
QgsAbstractGeometry* /Transfer/ )` constructor

* the python wrapper of the clone is garbage collected (that's where I
think cached type information should be cleared)

* then the QgsGeometry is garbage collected and the clone deleted along
(in C++, that's what Python can know nothing about, but by that time any
caching of information regarding the clone should have been invalidated
before if I interpret your previous statements correctly)


Is there something I am missing here?

Matthias




More information about the PyQt mailing list