QJsonValue QMetaObjectPublisher::invokeMethod(QObject *const object, const int methodIndex, const QJsonArray &args) { const QMetaMethod &method = object->metaObject()->method(methodIndex); if (method.name() == QByteArrayLiteral("deleteLater")) { // invoke `deleteLater` on wrapped QObject indirectly deleteWrappedObject(object); return QJsonValue(); } else if (!method.isValid()) { qWarning() << "Cannot invoke unknown method of index" << methodIndex << "on object" << object << '.'; return QJsonValue(); } else if (method.access() != QMetaMethod::Public) { qWarning() << "Cannot invoke non-public method" << method.name() << "on object" << object << '.'; return QJsonValue(); } else if (method.methodType() != QMetaMethod::Method && method.methodType() != QMetaMethod::Slot) { qWarning() << "Cannot invoke non-public method" << method.name() << "on object" << object << '.'; return QJsonValue(); } else if (args.size() > 10) { qWarning() << "Cannot invoke method" << method.name() << "on object" << object << "with more than 10 arguments, as that is not supported by QMetaMethod::invoke."; return QJsonValue(); } else if (args.size() > method.parameterCount()) { qWarning() << "Ignoring additional arguments while invoking method" << method.name() << "on object" << object << ':' << args.size() << "arguments given, but method only takes" << method.parameterCount() << '.'; } // construct converter objects of QVariant to QGenericArgument VariantArgument arguments[10]; for (int i = 0; i < qMin(args.size(), method.parameterCount()); ++i) { QVariant arg = args.at(i).toVariant(); if (method.parameterType(i) != QMetaType::QVariant && !arg.convert(method.parameterType(i))) { qWarning() << "Could not convert argument" << args.at(i) << "to target type" << method.parameterTypes().at(i) << '.'; } arguments[i].value = arg; } // construct QGenericReturnArgument QVariant returnValue; if (method.returnType() != qMetaTypeId<QVariant>() && method.returnType() != qMetaTypeId<void>()) { // Only init variant with return type if its not a variant itself, which would // lead to nested variants which is not what we want. // Also, skip void-return types for obvious reasons (and to prevent a runtime warning inside Qt). returnValue = QVariant(method.returnType(), 0); } QGenericReturnArgument returnArgument(method.typeName(), returnValue.data()); // now we can call the method method.invoke(object, returnArgument, arguments[0], arguments[1], arguments[2], arguments[3], arguments[4], arguments[5], arguments[6], arguments[7], arguments[8], arguments[9]); return wrapResult(returnValue); }
/*! Function for executing a slot that does not take parameters */ QString ObjectService::doCallMethod(TasCommand* command, QObject* target, QString& errorString) { Q_ASSERT(command->name() == "CallMethod"); QString methodName = command->parameter("method_name"); TasLogger::logger()->debug("name: " + methodName); int methodId = target->metaObject()->indexOfMethod( QMetaObject::normalizedSignature(methodName.toLatin1()).constData()); if (methodId == -1){ errorString.append(methodName + " method not found on object. "); TasLogger::logger()->debug("...method not found on object"); } else{ QMetaMethod metaMethod = target->metaObject()->method(methodId); QVariantList args = parseArguments(command); QList<QGenericArgument> arguments; for (int i = 0; i < args.size(); i++) { QVariant& argument = args[i]; QGenericArgument genericArgument( QMetaType::typeName(argument.userType()), const_cast<void*>(argument.constData())); arguments << genericArgument; } QVariant returnValue(QMetaType::type(metaMethod.typeName()), static_cast<void*>(NULL)); QGenericReturnArgument returnArgument( metaMethod.typeName(), const_cast<void*>(returnValue.constData())); if (!metaMethod.invoke( target, Qt::AutoConnection, // In case the object is in another thread. returnArgument, arguments.value(0), arguments.value(1), arguments.value(2), arguments.value(3), arguments.value(4), arguments.value(5), arguments.value(6), arguments.value(7), arguments.value(8), arguments.value(9))) { errorString.append(methodName + " method invocation failed! "); } else { return returnValue.toString(); } } return QString(""); }