如何使用QJSEngine构建API?

Gue*_*iro 2 javascript c++ qt qt5 qjsengine

我从Qt开始,我的一个项目是使用QJSEngine评估javascript,我想为脚本提供完整的API,包括类和全局函数。

现在,我的程序仅提供ECMAScript默认值(eval,encodeURI,parseInt等),但是我需要向代码公开一些自定义类,例如浏览器API(WebSocket类,Image类,文档对象)。例如:

var obj = new CustomClass("", 0);
var ret = obj.customClassMethod("[...]!");
customFunction(ret);
Run Code Online (Sandbox Code Playgroud)

我需要在C ++中定义类的行为,这无助于评估类定义并让用户代码运行。

Max*_*Max 5

与相比QScriptEngine,您可以添加自定义类(如果它们QObject使用Q_SCRIPT_DECLARE_QMETAOBJECT宏从中继承),而自定义类QJSEngine不会直接提供此功能。

您仍然可以使用Qt元对象系统为Javascript提供接口,但是您必须在C ++中实例化该对象并将其添加到Javascript上下文中。然后,可以在Javascript运行时内访问其插槽,用定义的方法Q_INVOKABLE以及用定义的属性Q_PROPERTY

现在,您可以创建一个工厂,该工厂CustomClassQJSEngine包装为Javascript对象的给定对象创建自定义类的实例:

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;
}
Run Code Online (Sandbox Code Playgroud)

需要构造一个工厂实例并将其添加到Javascript运行时的全局对象中:

QJSEngine engine;
QJSValue factoryObj = engine.newQObject(new CustomClassFactory());
engine.globalObject().setProperty("_customClassFactory", factoryObj);
Run Code Online (Sandbox Code Playgroud)

现在我们可以使用以下代码在Javascript中构造对象:

var obj = _customClassFactory.createInstance()
Run Code Online (Sandbox Code Playgroud)

到目前为止,让我们将自定义类的构造函数另外注入Javascript运行时:

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()"
    "}");
Run Code Online (Sandbox Code Playgroud)

等等,现在您可以用Javascript构造C ++对象,就像自定义Javascript类一样:

var obj = new CustomClass()
Run Code Online (Sandbox Code Playgroud)

对于提到的WebSocketAPI,您可以QtWebSocket为此目的进行包装-这正是我提出建议的方法时所需要的。

请注意,为简单起见,我省略了构造函数的参数,但也可以简单地添加它们。

PS:我会在官方文档中添加更多链接,但是由于缺乏声誉,我不允许这样做。