SIP: Retaining python class variables of derived C++ class

classic Classic list List threaded Threaded
3 messages Options
Reply | Threaded
Open this post in threaded view
|

SIP: Retaining python class variables of derived C++ class

Sandro Mani

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?

Thanks Sandro


_______________________________________________
PyQt mailing list    [hidden email]
https://www.riverbankcomputing.com/mailman/listinfo/pyqt
Reply | Threaded
Open this post in threaded view
|

Re: SIP: Retaining python class variables of derived C++ class

Phil Thompson-5
On 7 Jan 2019, at 4:32 pm, Sandro Mani <[hidden email]> 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?

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
_______________________________________________
PyQt mailing list    [hidden email]
https://www.riverbankcomputing.com/mailman/listinfo/pyqt
Reply | Threaded
Open this post in threaded view
|

Re: SIP: Retaining python class variables of derived C++ class

Nyall Dawson
On Tue, 8 Jan 2019 at 02:48, Phil Thompson <[hidden email]> wrote:

> > 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?
>
> 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.

This sounds very similar to the question asked here:
https://www.riverbankcomputing.com/pipermail/pyqt/2018-December/041177.html

But I've double checked, and the super type is indeed sip.wrapper for
both the item and registry classes. Calling sip.ispyowned before and
after transferring the item to the registry also confirms that the
ownership appears to have been transferred correctly (returns True
before the transfer, False after). But the python wrapper is still
deleted immediately as soon as it goes out of scope.

Got any other hints I could try?

Thanks,
Nyall
_______________________________________________
PyQt mailing list    [hidden email]
https://www.riverbankcomputing.com/mailman/listinfo/pyqt