[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