<html>
<head>
<meta http-equiv="content-type" content="text/html; charset=UTF-8">
</head>
<body text="#000000" bgcolor="#FFFFFF">
<p>Hi</p>
<blockquote type="cite"><span>On 7 Jan 2019, at 4:32 pm, <span
class="bold highlight search-highlight">Sandro</span> <span
class="bold highlight search-highlight">Mani</span> <</span><a
href="http://python.6.x6.nabble.com/user/SendEmail.jtp?type=node&node=5246016&i=0"
target="_top" rel="nofollow"><span>[hidden email]</span></a><span>>
wrote:
</span>
<div class="shrinkable-quote" style="height: 300px; overflow-y:
hidden;"><br>
<span>> </span><br>
<span>> Hi
</span><br>
<span>> </span><br>
<span>> I have the following scenario:
</span><br>
<span>> </span><br>
<span>> -----------
</span><br>
<span>> </span><br>
<span>> </span><br>
<span>> C++:
</span><br>
<span>> </span><br>
<span>> class AbstractItem {
</span><br>
<span>> AbstractItem(const QString& id);
</span><br>
<span>> virtual ~AbstractItem();
</span><br>
<span>> };
</span><br>
<span>> </span><br>
<span>> </span><br>
<span>> class Pool {
</span><br>
<span>> void addItem(AbstractItem* item /Transfer/);
</span><br>
<span>> AbstractItem* getItem(const QString& id);
</span><br>
<span>> };
</span><br>
<span>> </span><br>
<span>> </span><br>
<span>> </span><br>
<span>> </span><br>
<span>> Python:
</span><br>
<span>> </span><br>
<span>> class Item(AbstractItem):
</span><br>
<span>> def __init__(self, id):
</span><br>
<span>> AbstractItem.__init__(self, id)
</span><br>
<span>> self.value = "value"
</span><br>
<span>> def getValue(self):
</span><br>
<span>> return self.value
</span><br>
<span>> </span><br>
<span>> </span><br>
<span>> pool = Pool()
</span><br>
<span>> pool.addItem(Item("xyz"))
</span><br>
<span>> # ...
</span><br>
<span>> item = pool.getItem("xyz")
</span><br>
<span>> print(item.getValue()) ### AttributeError: 'Item'
object has no attribute 'value'
</span><br>
<span>> </span><br>
<span>> </span><br>
<span>> -----------
</span><br>
<span>> </span><br>
<span>> </span><br>
<span>> 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?
</span></div>
<div class="shrink-quote"><span>...</span> [<a>show rest of quote</a>]</div>
<br>
<span>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.
</span><br>
<br>
<span>Phil
</span></blockquote>
<p>PSA:<br>
</p>
<p>After the latest insights into how /Transfer/ works, I was able
to find a solution for this.</p>
<p>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.</p>
<p>To avoid this issue, there are the following possibilities I can
see</p>
<ul>
<li>Keep a reference to the item subclass (the current workaround)</li>
<li>Keep a (global or long-living) reference to the pool</li>
<li>And for singleton-like classes: add a /KeepReference/
annotation to the getter of the pool (see
<a class="moz-txt-link-freetext" href="https://github.com/qgis/QGIS/pull/9112">https://github.com/qgis/QGIS/pull/9112</a>)<br>
</li>
</ul>
<p>Regards</p>
<p>Matthias<br>
</p>
</body>
</html>