QMetaObject::invokeMethod call QML method from C++, with more than 10 arguments
-
I'm wondering how can I call
QMetaObject::invokeMethod
with many arguments.I know I can do like this for multiple arguments:
QMetaObject::invokeMethod( myobject, "methodname", Q_ARG(QVariant, 123), Q_ARG(QVariant, 123), Q_ARG(QVariant, 123), Q_ARG(QVariant, 123), Q_ARG(QVariant, 123), Q_ARG(QVariant, 123) ... );
My problem is that the function I'm trying to call has many (11) fields, and the signature for
QMetaObject::invokeMethod
is:bool QMetaObject::invokeMethod(QObject *obj, const char *member, Qt::ConnectionType type, QGenericReturnArgument ret, QGenericArgument val0 = QGenericArgument(nullptr), QGenericArgument val1 = QGenericArgument(), QGenericArgument val2 = QGenericArgument(), QGenericArgument val3 = QGenericArgument(), QGenericArgument val4 = QGenericArgument(), QGenericArgument val5 = QGenericArgument(), QGenericArgument val6 = QGenericArgument(), QGenericArgument val7 = QGenericArgument(), QGenericArgument val8 = QGenericArgument(), QGenericArgument val9 = QGenericArgument())
Therefore only up to 10 arguments are possible. Is there a way to circumvent this without splitting the method into 2?
-
@Developer123 said in QMetaObject::invokeMethod call QML method from C++, with more than 10 arguments:
without splitting the method into 2?
Why would you need to "split" the method? You can simply put at least some of the parameters into a struct and pass this struct as parameter. It is anyway bad design to have so many parameters in a function/method.
-
@jsulm Ok that's a good idea, do you know how can I do that? I tried passing a custom struct, such as:
MyStruct { int val1; int val2; }; MyStruct params; auto result = QMetaObject::invokeMethod( object, "mymethod", Q_ARG(QVariant, params)
But I get:
no instance of constructor "QArgument<T>::QArgument [with T=QVariant]" matches the argument list
.I'm using
QVariant
in theQ_ARG()
call because I want to access this variable in the QML side as a javascript object, not sure if it would be possible usingQ_ARG(MyStruct , params)
, even though that does compile... -
@Developer123 said in QMetaObject::invokeMethod call QML method from C++, with more than 10 arguments:
not sure if it would be possible using
Did you try?
You probably will need to register MyStruct, see https://doc.qt.io/qt-6/custom-types.html -
@jsulm Yep, tried and got error:
QMetaObject::invokeMethod: No such method SomeQObject_QMLTYPE_15::myMethod(MyStruct) Candidates are: myMethod(QVariant,QVariant,QVariant,QVariant,QVariant,QVariant,QVariant,QVariant,QVariant,QVariant,QVariant)
Also, I tried
Q_DECLARE_METATYPE(MyStruct);
on the header file containing the struct definition ofMyStruct
, same error... I guess I need to declare the class with the constructor, destructor, etc, instead of a struct, but I'm pretty sure that won't work out of the box.
Edit: I managed to send the QVariant doing:
MyStruct mystruct; QVariant params; params.setValue(mystruct); QMetaObject::invokeMethod( qobject, "myMethod", Q_ARG(QVariant, params) );
Now I'm stuck trying to access the values of
MyStruct
on QML. When I printparams
on QML, I get:qml: QVariant(MyStruct, )
-
@Developer123 add the
Q_GADGET
macro to your struct, make those public access function Q_INVOKABLE or, (probably better) define Q_PROPERTY(ies)Q_PROPERTY(int val1 MEMBER m_val1 CONSTANT FINAL)
IIRC this will require a
qRegisterMetaType
of your struct -
@J-Hilk Hello, I followed the steps exactly as defined here (they seem to correspond to your answer exactly).
I got some link errors. Then I cleaned the build and then it compiled and worked successfully. Thanks.
But I want to point out it was a lot of work to get this to work, I wish QT was simpler...
-
@Developer123 said in QMetaObject::invokeMethod call QML method from C++, with more than 10 arguments:
I wish QT was simpler...
Well, language interoperability (and C++ and QML are two different languages) is usually complicated at first. Once you have figured out how to interoperate it'll get a lot easier.