[Development] Qt5 API change coming up: QObject::connectNotify(const char *) --> connectNotify(QMetaMethod)

Kent Hansen kent.hansen at nokia.com
Mon Apr 30 14:14:00 CEST 2012


Hi all,
Quick links: https://bugreports.qt-project.org/browse/QTBUG-25541 and 
https://codereview.qt-project.org/#change,24282

(TL;DR; skip down to "IMPACT ON EXISTING connectNotify() REIMPLEMENTATIONS")

Yes, it's late, but it's also one of the final nails in the const char 
*-based Q(Meta)Object introspection API coffin.

We've had a nice template-based connect() in Qt for some time already. 
But the old connectNotify() hook was biased towards the original 
string-based connect(). To get connectNotify() to be called as expected 
by client code, the template-based connect() had to reconstruct the 
signal signature string (and prepend the darn QSIGNAL_CODE+'0' 
character). In Qt5, this is an even costlier operation, since the method 
signature is no longer stored verbatim in the QMetaObject data; it must 
be dynamically constructed from the name and parameter type information. 
Constructing a QMetaMethod, however, is very cheap; it's just a wrapper 
around a QMetaObject* and an index (which the QObject implementation has 
readily available when making/breaking connections). Once you have the 
QMetaMethod, you can also query all aspects of the method (such as the 
name, and parameter count), including its full signature 
(QMetaMethod::methodSignature()).

The other (public) shortcoming of the const char *-based connectNotify() 
is that if you were comparing the signal string to something else, you 
had to ensure that that "something else" was fully normalized. Otherwise 
the string comparison would fail (due to an extra space character, for 
example). In Qt5, there is an operator== for QMetaMethods, and there is 
the new QMetaMethod::fromSignal() function to get a QMetaMethod that 
corresponds to a C++ signal function. So you can easily compare methods 
without resorting to fragile, raw string comparisons.

This is why we're migrating away from the const char *-based API (yes, 
I'm also looking at you, QObject::receivers(const char *) ;-) ).


IMPACT ON EXISTING connectNotify() REIMPLEMENTATIONS

Existing reimplementations must be ported over to the new API in order 
to build with Qt5. I'm preparing patches for the places in Qt that I'm 
aware of. For a basic example, you can have a look at the QBuffer patch: 
https://codereview.qt-project.org/#change,24284.

For modules like qtsystems, which has dozens of connectNotify() 
reimplementations and performs signal proxying, it's more involved (WIP 
qtsystems patch: https://codereview.qt-project.org/#change,24817). 
However, we are keeping support for the old API for some time (obviously 
it will have to be removed before Qt5.0 final), to allow places outside 
of qtbase to be ported incrementally.

If there are places outside of the qt5 modules that need to be ported, I 
can help you with that.


IN RELATED NEWS...

In addition to the API change itself: We now call (dis)connectNotify() 
directly from the internal index-based 
QMetaObjectPrivate::(dis)connect() function. The nice thing about this 
is that connectNotify() reimplementations are called consistently "out 
of the box" (e.g., when you call connectSlotsByName(), or when QML 
connects to your signals -- and we could get rid of the hack that calls 
it from qtscript: https://codereview.qt-project.org/#change,24558). So 
the only remaining bug is that, as with the old API, disconnectNotify() 
is not called when the receiver is destroyed. But I'll propose a patch 
for fixing that (we will need to store the signal index in the internal 
Connection object, for fast retrieval of the QMetaMethod).

Best regards,
Kent


More information about the Development mailing list