Uploaded image for project: 'Qt'
  1. Qt
  2. QTBUG-114086

[Reg 6.4 -> 6.5] Historical NativeMethodBehavior is broken when a Q_INVOKABLE function is stored in a QML property

    XMLWordPrintable

Details

    • 4fdaf22a5 (dev), 544f50597 (6.5), 585ad82fa (6.6), 3c0b8076e (dev), f7f9aa00a (6.5), 0be66b13b (6.6)

    Description

      Related to https://doc.qt.io/qt-6/qtqml-cppintegration-exposecppattributes.html#c-methods-and-the-this-object

       

      Code
      cppobj.h

      class CppObj : public QObject
      {
          Q_OBJECT
          QML_ELEMENT
      
      public:
          CppObj(QObject* parent = nullptr) : QObject(parent) {}
      
          Q_INVOKABLE void sum(int a, int b)
          {
              qDebug().noquote() << this << QString("says %1 + %2 = %3").arg(a).arg(b).arg(a+b);
          }
      };
      

       

      Main.qml

      import QtQuick.Controls.Basic
      import InvokableProperty
      
      ApplicationWindow {
          width: 640
          height: 480
          visible: true
      
          property var qmlMethod: function(a, b) { console.log(`${this} says ${a} + ${b} = ${a+b}`) }
          property var cppMethod: objA.sum
      
          CppObj { id: objA; objectName: "objA" }
          CppObj { id: objB; objectName: "objB" }
      
          Button {
              text: "Calculate"
              onClicked: {
                  qmlMethod(1, 2)
                  qmlMethod.call(objB, 2, 1)
      
                  objA.sum(3, 4)
                  objA.sum.call(objB, 4, 3)
      
                  cppMethod(5, 6)
                  cppMethod.call(objB, 6, 5)
              }
          }
      }
      

       

      Steps to reproduce

      1. Build and run the test code
      2. Click the button 3 times

       

      Note: The enviroment variable QT_LOGGING_RULES="qt.qml.method.behavior=false;" is set to disable the note that is printed repeatedly in Qt 6.5:

      Calling C++ methods with 'this' objects different from the one they were retrieved from is broken, due to historical reasons. The original object is used as 'this' object. You can allow the given 'this' object to be used by setting 'pragma NativeMethodBehavior: AcceptThisObject'
      

       

      Qt 6.4.3 output, for every click (expected)
      This shows the expected (but erroneous) historical C++ output. The QML output is correct.

      qml: Main_QMLTYPE_3(0x2243e73ceb0) says 1 + 2 = 3
      qml: CppObj(0x2243b840b40, "objB") says 2 + 1 = 3
      CppObj(0x2243b840d60, name = objA) says 3 + 4 = 7
      CppObj(0x2243b840d60, name = objA) says 4 + 3 = 7
      CppObj(0x2243b840d60, name = objA) says 5 + 6 = 11
      CppObj(0x2243b840d60, name = objA) says 6 + 5 = 11
      

       

      Qt 6.5.1 output, for the 1st click (expected)
      Without pragma NativeMethodBehavior: AcceptThisObject, the historical behaviour is preserved as expected.

      qml: Main_QMLTYPE_3(0x1a177582a30) says 1 + 2 = 3
      qml: CppObj(0x1a1745d30f0, "objB") says 2 + 1 = 3
      CppObj(0x1a1745d2870, name = objA) says 3 + 4 = 7
      CppObj(0x1a1745d2870, name = objA) says 4 + 3 = 7
      CppObj(0x1a1745d2870, name = objA) says 5 + 6 = 11
      CppObj(0x1a1745d2870, name = objA) says 6 + 5 = 11
      

       

      Qt 6.5.1 output, for the 2nd and subsequent clicks (unexpected)
      The outputs of the 1st click are not reproduced. Instead, we get "Too many arguments, ignoring 1" when invoking `cppMethod` (in contrast with `objA.sum.call(objB, 4, 3)` which produces the expected historical output)

      qml: Main_QMLTYPE_3(0x1a177582a30) says 1 + 2 = 3
      qml: CppObj(0x1a1745d30f0, "objB") says 2 + 1 = 3
      CppObj(0x1a1745d2870, name = objA) says 3 + 4 = 7
      CppObj(0x1a1745d2870, name = objA) says 4 + 3 = 7
      expression for onClicked@qrc:/InvokableProperty/Main.qml:24
      Too many arguments, ignoring 1
      "Could not convert argument 0 at"
           "expression for onClicked@qrc:/InvokableProperty/Main.qml:24"
      Passing incomatible arguments to signals is not supported.
      expression for onClicked@qrc:/InvokableProperty/Main.qml:25
      Too many arguments, ignoring 1
      "Could not convert argument 0 at"
           "expression for onClicked@qrc:/InvokableProperty/Main.qml:25"
      Passing incomatible arguments to signals is not supported.
      

       

      Use case
      A customer has existing code where many Q_INVOKABLE methods are stored in properties and invoked directly, like 'cppMethod(5, 6)'

       

      Other notes

      • If using the test code from QTBUG-114090 instead of the one attached to this ticket, the 2nd click will crash at cppMethod.call(objB) on Qt 6.5.1
      • There is a typo in the warnings above: "incomatible"

      Attachments

        Issue Links

          No reviews matched the request. Check your Options in the drop-down menu of this sections header.

          Activity

            People

              ulherman Ulf Hermann
              skoh-qt Sze Howe Koh
              Votes:
              0 Vote for this issue
              Watchers:
              2 Start watching this issue

              Dates

                Created:
                Updated:
                Resolved:

                Gerrit Reviews