Qt meta-object system

What is is and why we need it?

From the Qt documentation we know that “Qt’s meta-object system provides the signals and slots mechanism for inter-object communication, run-time type information, and the dynamic property system.” [1]. I hope everyone knows what is signal-slot in Qt and why you need Q_OBJECT macro at the beginning of each class declaration.

Meta-object is also used for object casting using qobject_cast template function. It’s much more safe then build-in C++ cast functions and often is much faster. So qobject_cast(some_object) is better than dynamic_cast(some_object). Trust me :)

Deeper look

What is more interesting is how meta-object is implemented. Q_OBJECT macro adds some private declarations to each type (Q_OBJECT adds much more, but only thouse are interesting at this moment):

const QMetaObject *metaObject() const;
void *qt_metacast(const char *className);
int qt_metacall(QMetaObject::Call call, int id, void **arguments);

QMetaObject contains many useful information about class and object such as class name, properties, methods and so on. qt_metacast function is used by qobject_cast and I can’t image situation when I need call it directly. But qt_metacall function can be used to call method, read/write/reset property and do some other magic things :) which is defined by first argument (for example use QMetaObject::InvokeMetaMethod for method call). Second argument is method (or property) index and the third one is array of arguments (the first one is return value and maximum of 9 arguments can be passed to method). You can say that we need to know list of arguments and return type to call any function. You are right and QMetaObject offers this information. For example this code lists all public slots of self:

const QMetaObject *meta = metaObject();
for (int id = 0; id < meta->methodCount(); ++id) {
  const QMetaMethod method = meta->method(id);
  if (method.methodType() == QMetaMethod::Slot && method.access() == QMetaMethod::Public)
    qDebug() << method.name();

Information about return type and parameters can be retrieved by returnType() and parameterNames()/parameterTypes() methods.

Why i’m talking about all this things?

Using this information we can do many interesting things like creating object instances by class name

QObject *object = static_cast<QObject *>(QMetaType::create(QMetaType::type("QButton")));

so we can, for example, specify class name of some object in config and … call methods of this object also by name

object->qt_metacall(QMetaObject::InvokeMetaMethod, object->metaObject()->indexOfProperty("hello"), 0);

Real life example

As a real life example I can show you my old library (qtfjsonrpc) where i used meta-object system to simplify writing of APIs use json-rpc.

Thank you for reading ;)

Comments are welcome