如何使用QJSEngine构建API? [英] How to build an API with QJSEngine?
问题描述
我从Qt开始,我的一个项目是使用QJSEngine来评估javascript,我想为脚本提供一个完整的API,包括类和全局函数。
I am starting with Qt and one of my projects is using QJSEngine to evaluate javascript and I want to provide an entire API to the script, with classes and global functions.
现在我的程序只提供ECMAScript默认的东西(eval,encodeURI,parseInt等等),但我需要向代码公开一些自定义类,比如浏览器API(WebSocket类,Image类,文档对象) )。例如:
Right now my program provides only the ECMAScript default stuff (eval, encodeURI, parseInt, etc...), but I need to expose some custom classes to the code, like the browsers API (WebSocket class, Image class, document object). For example:
var obj = new CustomClass("", 0);
var ret = obj.customClassMethod("[...]!");
customFunction(ret);
我需要在C ++中定义类的行为,它无助于评估类的定义让用户代码运行。
I need to define the behavior of the classes in C++, it wouldn't help evaluate the classes definition and let the user code run.
推荐答案
与 QScriptEngine
相比,如果使用 QObject 继承自定义类,可以添加自定义类Q_SCRIPT_DECLARE_QMETAOBJECTrel =nofollow noreferrer> Q_SCRIPT_DECLARE_QMETAOBJECT
宏, QJSEngine
不直接提供此功能。
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.
您仍然可以使用Qt元对象系统为Javascript提供接口,但您必须在C ++中实例化该对象并将其添加到Javascript上下文中。
那么它的插槽,用 Q_INVOKABLE
定义的方法,以及用 Q_PROPERTY
定义的属性都可以从Javascript运行时。
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 it's slots, methods defined with Q_INVOKABLE
, and properties defined with Q_PROPERTY
are all accessible from within the Javascript runtime.
现在您可以创建一个工厂,为给定的<$创建自定义类 CustomClass
的实例c $ c> QJSEngine 包装为Javascript对象:
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;
}
需要构建工厂实例并将其添加到Javascript的全局对象中运行时:
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);
现在我们可以用Javascript构建对象:
Now we can construct objects in Javascript with:
var obj = _customClassFactory.createInstance()
当我们走到这一步时,让我们另外将自定义类的构造函数注入Javascript运行时:
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()"
"}");
Etvoilà,现在你可以在Javascript中构建C ++对象,就像你自定义Javascript类一样:
Et voilà, now you can construct C++ object in Javascript, like you would custom Javascript classes:
var obj = new CustomClass()
对于上面提到的 WebSocket
API,你可以包装 QtWebSocket
为此目的 - 这正是我提出建议方法时所需要的。
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:我会添加更多官方文档的链接,但由于缺乏声誉,我不允许。
PS: I would have added more links to the official documentation, but due to the lack of reputation I'm not allowed to.
这篇关于如何使用QJSEngine构建API?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!