On Mon, 7 Dec 2009 16:24:19 -0800 (PST), Christian Roche <[email protected]> wrote: > However now I have another problem. Following Phill latest advice, I read > the following part of the documentation: > > >> In the current version QVariant.userType() will correctly return >> QMetaType.QObjectStar (or QMetaType.QWidgetStar) but an extra reference >> to >> the Python object is not kept. To avoid a potential crash you should >> ensure that you keep a separate reference to the Python object, either >> explicitly or implicitly by giving it a parent. >> > Unfortunaltely these sentences are totally unclear to me. When is > QVariant.userType() used? Who does or does not keep a reference to the > Python object, and when? In which situation would a crash potentially > occur?
When a value is passed between threads Qt wraps it in a QVariant and uses the event system to send it to the correct thread. PyQt can convert any Python object to a QVariant. If possible it uses the standard QVariant types to do so. This means that if the code using the value is C++ then it has a chance of working. The original Python object gets discarded, ie. it's reference count is left unchanged. This is fine because the standard QVariant types (with a couple of exceptions) are value types (as opposed to pointer types) so they can be safely copied by Qt and exist independently of the original Python object. Other Python objects do not correspond to the standard QVariant types, so PyQt has an internal C++ class that can wrap a Python object and can itself be wrapped in a QVariant. As a QVariant can be copied around inside Qt the internal PyQt class manages the reference count of the Python object it is wrapping so that it stays alive for as long as it is needed, and garbage collected when it is not. All the above happens automatically. The problem is that the QObjectStar and QWidgetStar types are pointer types and not value types. If the value being pointed to is owned by Python then it's important that the reference count is maintained, otherwise the QObject/QWidget will be destroyed when the Python object is garbage collected and the QVariant will be left with a dangling pointer and will cause a crash. Ideally these types would be wrapped by the same internal PyQt class which would manage the reference count. The problem is that any C++ code that is expecting a QObjectStar/QWidgetStar wouldn't know how to get it out of the wrapper. The main use case is making Python objects available as JavaScript objects in QtScript. Therefore, in these specific cases, if it necessary for your code to ensure that there is an explicit reference kept to any QObject or QWidget you are passing between threads. > Worse, eventhough I don't understand the "why", I tried to implement the > "how", i.e., naively added the following lines to my code, hoping to have > given my poor lonesome QObject some parent by doing so, and not any > ordinary > parent, the parent of all parents, the very QApplication itself: > > >> class ImageLink(QObject): >> >> def __init__(self, base, url, href): >> QObject.__init__(self) >> app = QApplication.instance() >> self.moveToThread(app.thread()) >> self.setParent(app) >> blah blah >> > Alas, poor Yorich, all this no no avail. Still it crashes faster than the > lightning, and grieves my sore heart and my tired soul. I've already suggested that you should simplify your ImageLink class so that it does not derive from QObject. Phil _______________________________________________ PyQt mailing list [email protected] http://www.riverbankcomputing.com/mailman/listinfo/pyqt
