[PySide] Bug with new hash table feature

Nathan Smith nathanjsmith at gmail.com
Thu Jun 14 00:32:26 CEST 2012


We don't want to raise a RuntimeError when calling the hash function in
Shiboken because of the very reason you stated.  Doing something that
raises exceptions in the hash function will break any container that uses
hashes (weak references, sets, dicts, weakref.WeakSet, probably many more).
 Returning default error values has a similar effect.

My most recent approach was to return the address of the shiboken object,
which is address of the PyObject.  I tried this approach (I haven't
submitted it yet) on the example you provided below, and it seems to work.
 I've been using it with my code for a few days now, and it's been working
well.

Note that using the address method has the drawback that two objects
separated in time may have the same hash value because they may land at the
same memory address.  You can see this in the following test case:

>>> hash(QtCore.QObject()) == hash(QtCore.QObject())
True


The first QObject is created, the hash is taken of it, and then it is
destroyed.  The reference count drops to 0, so the Shiboken handle is
cleaned up.  A second QObject is created (at the same address as the first
QObject), the hash is taken of it, and then it is destroyed.  This could be
avoided if we kept a running counter of SbkObject instances and used the
counter as the hash value (which I think is overkill).

Incidentally, what is the difference between shiboken.delete and
shiboken.invalidate?  There don't appear to be any docstrings in the
shiboken module and invalidate isn't in the online documentation.

Nathan


On Wed, Jun 13, 2012 at 3:45 PM, John Ehresman <jpe at wingware.com> wrote:

> On 5/30/12 3:35 PM, John Ehresman wrote:
>
>> Can we use the address of the Shiboken object as the hash value?  That
>>> remains valid so long as there are references to the object, even after
>>> the object itself has been deleted in C++ land.
>>>
>>
>> This works if there can only be one wrapper at a time for a given
>> QObject.  I don't know if this is the case.
>>
>
> I just ran into this bug and tried to apply the patch locally, but ran
> into poblems.  If the address of the PyObject* can be used, I think that
> would be preferable.  Consider the following:
>
>    o = QObject()
>    d = {}
>    d[o] = 1
>    def on_destroy():
>        d.pop(o)
>    o.destroyed.connect(on_**destroy)
>    shiboken.delete(o)
>
> The pop in the destroy handler will fail with a RuntimeError and even if
> the RuntimeError is suppressed and a default hash value returned, the entry
> in the dictionary won't be found or removed.
>
> John
>
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://lists.qt-project.org/pipermail/pyside/attachments/20120613/5e025814/attachment.html>
-------------- next part --------------
A non-text attachment was scrubbed...
Name: hash.patch
Type: application/octet-stream
Size: 1381 bytes
Desc: not available
URL: <http://lists.qt-project.org/pipermail/pyside/attachments/20120613/5e025814/attachment.obj>


More information about the PySide mailing list