QMetaObject::newInstance() in Qt 4.5

Yesterday I was getting the smoke bindings lib to build with Qt 4.5 with krege on irc, and one of the errors we were getting was with a private class called 'QMetaObjectExtras' that was failing to compile. I fixed it by making the generator skip that class, but I wondered what was in it. This morning I had a look and it turns out that the new moc has a very interesting and useful new feature; you can now have constructors in your QMetaObjects.

To get a constructor added to the QMetaObject, you just prefix it with Q_INVOKABLE like this:

Q_INVOKABLE MyWidget(QWidget* parent = 0);

The moc generates a static_metacall() function that looks like this:

static int MyWidget_qt_static_metacall(QMetaObject::Call _c, int _id, void **_a)
    if (_c == QMetaObject::CreateInstance) {
        switch (_id) {
        case 0: { MyWidget *_r = new MyWidget((*reinterpret_cast< QWidget*(*)>(_a[1])));
            if (_a[0]) *reinterpret_cast(_a[0]) = _r; } break;
        case 1: { MyWidget *_r = new MyWidget();
            if (_a[0]) *reinterpret_cast(_a[0]) = _r; } break;
        _id -= 2;
        return _id;
    _id = MyWidget::staticMetaObject.superClass()->static_metacall(_c, _id, _a);
    if (_id < 0)
        return _id;
    return _id;

Note that it generates a handy no args constructor too. You can query the QMetaObject for constructors using constructorCount() and constructor(int) to obtain the QMetaMethods corresponding to the constructors. To dynamically invoke the constructor you call the newInstance() method on the staticMetaObject like this:

MyWidget * widget = MyWidget::staticMetaObject::newInstance( Q_ARG(QObject, myParent) );

This is really useful for language bindings as you can pretty much get a complete binding 'for free', that will allow you to call slots, connect to signals, get and set properties, create new instances and retrieve enum values. In a language like Ruby it is just a matter of getting hold of a QMetaObject to do all of this with no extra code. With a static language like C# it would still be necessary to generate a C# wrapper, but no extra native code would be needed. I think we can hack the moc to generate the C# wrappers, and the only thing that would be nice would be a plugin code generator option for the moc so we don't have to fork the code in bindings projects.

For the GObject Introspection QMetaObject project that I'm working on, the ability to put the constructors in the per instance QMetaObjects is very useful. Otherwise, I was going to put them in the per-GObject namespace singleton classes.


I wonder what does this mean for QtScript. Currently to make a class that can be created in QtScript you have to create a constructor and pass it a function pointer (it all seems like something out of C code).

By eean at Thu, 02/19/2009 - 17:12

This is cool! When I first saw the title, I thought that this breaks the singleton pattern (like in Java), but having Q_INVOKABLE mandatory is a good solution :)

By Ivan Čukić at Thu, 02/19/2009 - 18:38

Do you mean we no longer need SMOKE?

By Pau Garcia i Quiles at Fri, 02/20/2009 - 21:15

Do you mean we no longer need SMOKE?

No quite, there are a few features which Smoke provides:

  • Callbacks for overriding virtual methods
  • Callbacks for when an instance is deleted
  • Works with non-QObject classes
  • Handles multiple inheritance

Although for the last point, the new Qt 4.5 QMetaObjects has an array of meta objects in the QMetaObjectExtraData, which looks like it might be possible to support multiple inheritance. I haven't worked out how to get the new moc to generate those yet.

By Richard Dale at Mon, 02/23/2009 - 16:40