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

QJSEngine/QQmlEngine: Support instantiating C++ classes in JavaScript using `new`

    XMLWordPrintable

Details

    Description

      Qt Script supports defining a new JavaScript constructor like this:

      void ScriptContext::defineClass(const QString &className, QScriptEngine::FunctionSignature constructor)
      {
          QScriptValue ctor = interpreter.newFunction(constructor);
          QScriptValue metaObject = interpreter.newQMetaObject(&QObject::staticMetaObject, ctor);
          interpreter.globalObject().setProperty(className, metaObject);
      }
      

      QJSEngine/QQmlEngine lacks similar functionality. Q_INVOKABLE constructors are not accessible from JavaScript.

       

      Closest workaround

      Register a QML singleton with a member function that returns an instance of the object:

      // scriptable.h
      class InstantiableCppObj : public QObject
      {
          Q_OBJECT
          Q_PROPERTY(QString name MEMBER m_name NOTIFY nameChanged)
      
      public:
          Q_INVOKABLE InstantiableCppObj(const QString &name = QString(), QObject *parent = nullptr);
      
      ...
      };
      
      class CppUtils : public QObject
      {
          Q_OBJECT
      
      public:
          Q_INVOKABLE InstantiableCppObj* newInstantiableCppObj(const QString &name) { return new InstantiableCppObj(name); }
      };
      
      
      // main.qml
      let cppObj = CppUtils.newInstantiableCppObj('Obj A')
      console.log("Created a new C++ object from JavaScript called " + cppObj.name)
      

       

      Output:

      qml: Created a new C++ object from JavaScript called Obj A

       

      Attempts that didn't work

      let cppObjB =     InstantiableCppObj('Obj B')                    // [1][3]
      let cppObjC = new InstantiableCppObj('Obj C')                    // [2]
      let cppObjD =     InstantiableCppObj.InstantiableCppObj('Obj D') // [1][4]
      let cppObjE = new InstantiableCppObj.InstantiableCppObj('Obj E') // [2]
      

      [1] M306: Call of functions that start with an uppercase letter should use 'new'.
      [2] TypeError: Type error
      [3] TypeError: Property 'InstantiableCppObj' of object [null] is not a function
      [4] TypeError: Property 'InstantiableCppObj' of object [object Object] is not a function

      Attachments

        Issue Links

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

          Activity

            People

              qtqmlteam Qt Qml Team User
              skoh-qt Sze Howe Koh
              Votes:
              2 Vote for this issue
              Watchers:
              3 Start watching this issue

              Dates

                Created:
                Updated:

                Gerrit Reviews

                  There are no open Gerrit changes