[PyQt] SIP: Retaining python class variables of derived C++ class

Sandro Mani manisandro at gmail.com
Wed Feb 6 11:54:29 GMT 2019


On 06.02.19 12:41, Matthias Kuhn wrote:
>
> Hi
>
>> On 7 Jan 2019, at 4:32 pm, Sandro Mani <[hidden email] 
>> <http://python.6.x6.nabble.com/user/SendEmail.jtp?type=node&node=5246016&i=0>> 
>> wrote:
>>
>> > 
>> > Hi 
>> > 
>> > I have the following scenario: 
>> > 
>> > ----------- 
>> > 
>> > 
>> > C++: 
>> > 
>> > class AbstractItem { 
>> >     AbstractItem(const QString& id); 
>> >     virtual ~AbstractItem(); 
>> > }; 
>> > 
>> > 
>> > class Pool { 
>> >     void addItem(AbstractItem* item /Transfer/); 
>> >     AbstractItem* getItem(const QString& id); 
>> > }; 
>> > 
>> > 
>> > 
>> > 
>> > Python: 
>> > 
>> > class Item(AbstractItem): 
>> >     def __init__(self, id): 
>> >         AbstractItem.__init__(self, id) 
>> >         self.value = "value" 
>> >     def getValue(self): 
>> >         return self.value 
>> > 
>> > 
>> > pool = Pool() 
>> > pool.addItem(Item("xyz")) 
>> > # ... 
>> > item = pool.getItem("xyz") 
>> > print(item.getValue()) ### AttributeError: 'Item' object has no attribute 'value'
>> > 
>> > 
>> > ----------- 
>> > 
>> > 
>> > The issue is that, when I pass the Python-deriver Item instance to the pool, lose the reference to it, and then 
>> re-retreive it from the pool, the Item instance will have lost class 
>> variables set in the Item __init__ function. As I understand, this is 
>> expected, because SIP keeps a python part and a c++ part of each 
>> object, and the python part is garbage-collected when the variable 
>> gets out of scope. Is there a way to make the above logic work?
>> ... [show rest of quote]
>>
>> Use of /Transfer/ should get the behaviour that you want. However you 
>> need to make sure you are using the right supertype for any classes 
>> that implement any sort of ownership rules. Adding the 
>> /Supertype=sip.wrapper/ class annotation to both AbstractItem and 
>> Pool classes may help.
>>
>> Phil 
>
> PSA:
>
> After the latest insights into how /Transfer/ works, I was able to 
> find a solution for this.
>
> As soon as the Transfer annotation is involved, the target class 
> wrapper (the pool in this case) will hold a reference to the 
> transferred child wrapper (item subclass here). If pool's wrapper gets 
> garbage collected, the transferred item's wrapper is free to be 
> garbage collected as well.
>
> To avoid this issue, there are the following possibilities I can see
>
>   * Keep a reference to the item subclass (the current workaround)
>   * Keep a (global or long-living) reference to the pool
>   * And for singleton-like classes: add a /KeepReference/ annotation
>     to the getter of the pool (see https://github.com/qgis/QGIS/pull/9112)
>
Thanks for the followup!

Sandro

-------------- next part --------------
An HTML attachment was scrubbed...
URL: <https://www.riverbankcomputing.com/pipermail/pyqt/attachments/20190206/fff15d75/attachment.html>


More information about the PyQt mailing list