Tomáš Zato Tomáš Zato - 2 months ago 16
C++ Question

How to invoke QMetaMethod with an array of QStrings?

QMetaObject system provides some basic reflection API. What I want to do is to call given slot or method that's available through this system.

However, the arguments and names of method are initially all QString values. The documentation shows an example:


QString retVal;
QByteArray normalizedSignature = QMetaObject::normalizedSignature("compute(QString, int, double)");
int methodIndex = obj->metaObject()->indexOfMethod(normalizedSignature);
QMetaMethod method = obj->metaObject()->method(methodIndex);
method.invoke(obj,
Qt::DirectConnection,
Q_RETURN_ARG(QString, retVal),
Q_ARG(QString, "sqrt"),
Q_ARG(int, 42),
Q_ARG(double, 9.7));


If the "compute" slot does not take exactly one QString, one int and
one double
in the specified order, the call will fail.


Emphasis mine. Now with this example, I'm pretty clueless. It's clearly using templates, which are useless in dynamic context. I don't really see a purpose in using this API statically, when I could just as well call the method directly.

So let's say I have this function:

void invokeSlot(QObject* target, const QString& slotName, const QStringList& arguments) {
// This is how I can get list of overloads by given name
const QMetaObject* obj = target_->metaObject();
QList<QMetaMethod> overloads;
for (int i = 0, l = obj->methodCount(); i < l; ++i) {
const QMetaMethod method = obj->method(i);
if( method.name() == name )
overloads.append(method);
}
// Now how to convert the arguments?
}


You can assume that I have prepared this method for type conversion:

QVariant convertType(const QString& source, const QVariant::Type requiredType);


But how to pass the arguments even if I chose correct overload and convert strings to QVariants of required type?

Answer

You can prepare this function:

QGenericArgument convertType(const QString& source, const QVariant::Type requiredType);

By using switches and Q_ARG inside it.

Then a big switch on the argument count with invokes in it.

Comments