How to build an API with QJSEngine?

為{幸葍}努か 提交于 2019-12-04 17:00:14

In contrast to QScriptEngine, where you can add custom classes if they inherit from QObject by using the Q_SCRIPT_DECLARE_QMETAOBJECT macro, the QJSEngine does not directly provide this functionality.

You can still use the Qt Meta-object system to provide interfaces for Javascript, but you have to instantiate the object in C++ and add it to the Javascript context. Then its slots, methods defined with Q_INVOKABLE, and properties defined with Q_PROPERTY are all accessible from within the Javascript runtime.

Now you can create a factory which creates instances of your custom class CustomClass for a given QJSEngine wrapped as Javascript objects:

class CustomClassFactory : public QObject
{
    Q_OBJECT
public:
  CustomClassFactory(QJSEngine* engine) : m_engine(engine) {}
  Q_INVOKABLE QJSValue createInstance() {
      // The engine takes ownership and destroys the object if no longer required.
      return m_engine->newQObject(new CustomClass());
  }
private:
    QJSEngine* m_engine;
}

A factory instance needs to be constructed and added to the global object of the Javascript runtime:

QJSEngine engine;
QJSValue factoryObj = engine.newQObject(new CustomClassFactory());
engine.globalObject().setProperty("_customClassFactory", factoryObj);

Now we can construct objects in Javascript with:

var obj = _customClassFactory.createInstance()

As we've come this far, lets additionally inject a constructor for the custom class into the Javascript runtime:

QJSEngine engine;
// Again, the QJSEngine will take ownership of the created object.
QJSValue factoryObj = engine.newQObject(new CustomClassFactory());
engine.globalObject().setProperty("_customClassFactory", factoryObj);
engine.evaluate(
    "function CustomClass() {"
    "    return _customClassFactory.createInstance()"
    "}");

Et voilà, now you can construct C++ object in Javascript, like you would custom Javascript classes:

var obj = new CustomClass()

For the mentioned WebSocket API you could wrap QtWebSocket for that purpose – that was exactly what I required when I came up with the proposed approach.

Note that for the sake of simplicity I omitted parameters for the constructor, but they can simply be added as well.

PS: I would have added more links to the official documentation, but due to the lack of reputation I'm not allowed to.

If you look up Documentation of QScriptEngine, or by searching "QScriptEngine examples" you can find some stuff about making Custom C++ Classes available to QScriptEngine.

Here is a good place to start: link to example

QScriptEngine is very similiar to QJsEngine, so it shouldn't be a big problem for you.

Hope this helps :)

As of Qt5.5 QScriptEngine has been deprecated, so only QJsEngine should be used in the future. https://wiki.qt.io/New_Features_in_Qt_5.5#Deprecated_Functionality

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!