Skip to content
  • Categories
  • Recent
  • Tags
  • Popular
  • Users
  • Groups
  • Search
  • Get Qt Extensions
  • Unsolved
Collapse
Brand Logo
  1. Home
  2. Qt Development
  3. General and Desktop
  4. QMetaObject::invokeMethod call QML method from C++, with more than 10 arguments
QtWS25 Last Chance

QMetaObject::invokeMethod call QML method from C++, with more than 10 arguments

Scheduled Pinned Locked Moved Unsolved General and Desktop
8 Posts 4 Posters 1.3k Views
  • Oldest to Newest
  • Newest to Oldest
  • Most Votes
Reply
  • Reply as topic
Log in to reply
This topic has been deleted. Only users with topic management privileges can see it.
  • D Offline
    D Offline
    Developer123
    wrote on last edited by Developer123
    #1

    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?

    jsulmJ 1 Reply Last reply
    0
    • D Developer123

      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?

      jsulmJ Offline
      jsulmJ Offline
      jsulm
      Lifetime Qt Champion
      wrote on last edited by
      #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.

      https://forum.qt.io/topic/113070/qt-code-of-conduct

      D 1 Reply Last reply
      2
      • jsulmJ jsulm

        @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.

        D Offline
        D Offline
        Developer123
        wrote on last edited by Developer123
        #3

        @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 the Q_ARG() call because I want to access this variable in the QML side as a javascript object, not sure if it would be possible using Q_ARG(MyStruct , params), even though that does compile...

        jsulmJ 1 Reply Last reply
        0
        • D Developer123

          @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 the Q_ARG() call because I want to access this variable in the QML side as a javascript object, not sure if it would be possible using Q_ARG(MyStruct , params), even though that does compile...

          jsulmJ Offline
          jsulmJ Offline
          jsulm
          Lifetime Qt Champion
          wrote on last edited by
          #4

          @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

          https://forum.qt.io/topic/113070/qt-code-of-conduct

          D 1 Reply Last reply
          0
          • jsulmJ jsulm

            @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

            D Offline
            D Offline
            Developer123
            wrote on last edited by Developer123
            #5

            @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 of MyStruct, 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 print params on QML, I get:

            qml: QVariant(MyStruct, )

            J.HilkJ 1 Reply Last reply
            0
            • D Developer123

              @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 of MyStruct, 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 print params on QML, I get:

              qml: QVariant(MyStruct, )

              J.HilkJ Offline
              J.HilkJ Offline
              J.Hilk
              Moderators
              wrote on last edited by
              #6

              @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


              Be aware of the Qt Code of Conduct, when posting : https://forum.qt.io/topic/113070/qt-code-of-conduct


              Q: What's that?
              A: It's blue light.
              Q: What does it do?
              A: It turns blue.

              D 1 Reply Last reply
              3
              • J.HilkJ J.Hilk

                @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

                D Offline
                D Offline
                Developer123
                wrote on last edited by Developer123
                #7

                @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...

                S 1 Reply Last reply
                1
                • D Developer123

                  @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...

                  S Offline
                  S Offline
                  SimonSchroeder
                  wrote on last edited by
                  #8

                  @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.

                  1 Reply Last reply
                  1

                  • Login

                  • Login or register to search.
                  • First post
                    Last post
                  0
                  • Categories
                  • Recent
                  • Tags
                  • Popular
                  • Users
                  • Groups
                  • Search
                  • Get Qt Extensions
                  • Unsolved