Javascript 如何使用QJSEngine构建API?

Javascript 如何使用QJSEngine构建API?,javascript,c++,qt,qt5,qjsengine,Javascript,C++,Qt,Qt5,Qjsengine,我从Qt开始,我的一个项目是使用QJSEngine评估javascript,我想为脚本提供一个完整的API,包括类和全局函数 现在,我的程序只提供ECMAScript默认内容(eval、encodeURI、parseInt等),但我需要向代码公开一些自定义类,比如浏览器API(WebSocket类、图像类、文档对象)。例如: var obj=new CustomClass(“,0); var ret=obj.customClassMethod(“[…]!”); 定制功能(ret); 我需要定义

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

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

var obj=new CustomClass(“,0);
var ret=obj.customClassMethod(“[…]!”);
定制功能(ret);

我需要定义C++中类的行为,它不利于评估类定义,让用户代码运行。

< P>如果查阅QScript引擎的文档,或者通过搜索“QScript引擎示例”,您可以找到一些关于自定义C++类可用于QScript引擎的东西。 这里是一个很好的起点:

QScript引擎与QJsEngine非常相似,所以对您来说应该不是什么大问题


希望这有帮助:)

QScriptEngine
相比,如果自定义类通过使用宏从
QObject
继承,则可以添加自定义类,
QJSEngine
不直接提供此功能

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

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

class CustomClassFactory:公共QObject
{
Q_对象
公众:
CustomClassFactory(QJSEngine*引擎):m_引擎(引擎){}
Q_可调用的QJSValue createInstance(){
//如果不再需要,引擎将获得所有权并销毁对象。
返回m_engine->newQObject(newcustomclass());
}
私人:
QJSEngine*m_发动机;
}
需要构造工厂实例并将其添加到Javascript运行时的全局对象:

QJSEngine;
QJSValue factoryObj=engine.newQObject(newcustomclassfactory());
engine.globalObject().setProperty(“\u customClassFactory”,factoryObj);
现在,我们可以使用以下方法在Javascript中构造对象:

var obj=\u customClassFactory.createInstance()
至此,让我们将自定义类的构造函数另外注入Javascript运行时:

QJSEngine;
//同样,QJSEngine将获得所创建对象的所有权。
QJSValue factoryObj=engine.newQObject(newcustomclassfactory());
engine.globalObject().setProperty(“\u customClassFactory”,factoryObj);
发动机评估(
“函数CustomClass(){”
“返回\u customClassFactory.createInstance()”
"}");
java,现在可以在JavaScript中构造C++对象,就像你定制的JavaScript类:

var obj=new CustomClass()
对于所提到的
WebSocket
API,您可以为此目的包装
QtWebSocket
——这正是我提出建议方法时所需要的

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


PS:我本来可以添加更多到官方文档的链接,但由于缺乏声誉,我不被允许添加。

从Qt5.5开始,QScript Engine已被弃用,因此今后只能使用
QJsEngine

在Qt5.8中,QJSEngine添加了一个新功能:
newQMetaObject

您只需使用上述函数将静态元对象(例如
&MyQObjectDerivedClass::staticMetaObject
)添加到JSEngine

然后,您将能够从QML中
新建
Javascript中的那些对象。我发现这是一个非常巧妙的解决方案

正如文档所说,您必须将构造函数标记为可调用的,否则您将无法实例化类的对象

属性系统(setters/getter)与插槽一样正常工作

这是我的测试代码——首先是添加元对象< /p>的C++部分

QQmlApplicationEngine engine;
QJSValue jsMetaObject = engine.newQMetaObject(&MyClassOfObject::staticMetaObject);
engine.globalObject().setProperty("MyClassOfObject", jsMetaObject);
我现在可以编写JS,使其
news
成为该类型的对象,并使用setter/getter等。该代码实际上存在于用于手动测试的MouseArea onClicked处理程序中

var bob = new MyClassOfObject();
print(bob.x);
bob.x = 918264;
print(bob.x);
print(bob.words);
这是类的定义

class MyClassOfObject : public QObject
{
    Q_OBJECT
    Q_PROPERTY(int x READ getX WRITE setX)
    Q_PROPERTY(int y READ getY WRITE setX)
    Q_PROPERTY(QStringList words READ getWords)    
public:
    Q_INVOKABLE explicit MyClassOfObject(QObject *parent = nullptr);
public slots:
    int getX() const { return x; }
    int getY() const { return y; }
    void setX(int x) { this->x = x; }
    void setY(int y) { this->y = y; }
    QStringList getWords() const;
private:
    int x = -113;
    int y = 616;
    QStringList stringList;
};

QJSEngine在使用属性为r、g、b的类Color:public QObject遵循您的建议后抱怨:“ReferenceError:Color未定义”。3个标记为Q_可调用的构造函数。有什么我可能错过的吗?我使用QScript引擎来管理它。有什么想法吗?@laune-我已经更新了原来的帖子。我希望这有帮助。我会先检查“setProperty”中给出的名称。抱歉,如果您收到很多“编辑”消息。我对SO很陌生!非常感谢-它很有效!我将上一次工作中的setProperty(参见Max的答案)定义得一干二净,认为newQMetaObject方法可以处理所有事情。事实上,如果类名和属性名一样好的话,可能会这样,但是现在我看到增强的灵活性重新命名并包含对象仍然保证了额外的调用。@laune。是-如果您需要经常这样做,那么可以使用静态元对象的
className
成员自动推断属性名。这非常有用!适用于类颜色:public QObject,具有属性r、g、b加上getR/g/b和setR/g/b,三个构造函数和方法toHex和toStr。但是:只要我使用toString,该方法就会返回s.th。比如“颜色(0x564cfa5c3c10)”。有什么想法吗?@laune
QColor
可能没有
toString()
成员。你要找的可能是。对于十六进制字符串,您应该能够调用
color.name(0)