使用Qt QJSEngine实现JavaScript与C++混合编程

本文介绍了如何使用Qt的QJSEngine进行JavaScript与C++的混合编程,包括执行JavaScript代码、处理脚本异常以及在JavaScript中调用C++的类对象和属性。QJSEngine基于Chrome的V8引擎,提供了方便的接口来交互。通过设置全局对象属性、创建类对象代理以及利用QMetaObject,可以在JavaScript环境中直接调用C++的方法和属性。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

原文链接:https://blog.csdn.net/douzhq/article/details/105374313

QJSEngine实现了一个Qt中JavaScript的运行环境,使用的是Chrome的V8引擎。
下面介绍一下QJSEngine的简单使用。

1. 执行JavaScript的代码

使用函数 evaluate 实现执行一个JavaScript脚本。

QJSEngine* jsEngine = new QJSEngine(this);
// 执行Js代码
QJSValue value = jsEngine->evaluate("1+1");
qDebug() << "1 + 1 Result is " << value.toInt();

QJSValue 是一个Qt/JavaScript包装的一个类型。
也可以使用 QJSValue::call 函数,传递参数给一个JavaScript的函数。

QJSValue function = jsEngine->evaluate("(function(a, b){return a + b;})");
QJSValueList args;
args << 10 << 20;
QJSValue funcValue = function.call(args);
qDebug() << "Function Result is " << funcValue.toInt();

2. 脚本异常

在Qt环境中,执行JavaScript函数。如果出现语法错误等问题,在Qt环境中是如何获取的呢?
同样在脚本执行的 QJSValue 类中,可以获取是否执行出错,以及一些错误信息。

// Error
QJSValue errorValue = jsEngine->evaluate("...");
if (errorValue.isError())
{
    qDebug() << "Error!";
    qDebug() << errorValue.property("name").toString() << ", " \
             << errorValue.property("message").toString();
    qDebug() << errorValue.property("lineNumber").toInt();
}

输出结果如下:
Error!
“SyntaxError” , “Expected token `;’”
1

下面是一些可使用的属性:

  • name : 名字
  • message :错误的信息
  • fileName : 文件名,evaluate 函数也可以指定一个文件名,它的作用也仅用于次。如果想加载一个文件运行,则必须加载到内存中,然后将文件的内容传递到该函数中。
  • lineNumber :错误行号
  • stack :调用堆栈。

3. JavaScript中调用C++

(1)添加全局对象属性

函数 globalObject() 会返回一个全局对象。

jsEngine->globalObject().setProperty("CustomNumber", 100);
value = jsEngine->evaluate("CustomNumber + 1");
qDebug() << "Result is " << value.toInt();

设置全局属性 CustomNumber 初始值为100 。
JavaScript环境中,可以直接使用该属性。

(2)添加类对象属性

使用函数 newQObject() 包裹一个 QObject 或者它的子类,返回一个JavaScript的代理类。在这个代理类中,可以使用它的属性、信号和槽函数。也可以使用函数 newObject() 创建一个普通的JavaScript类对象。

下面是一个简单的示例:
类声明:

class JsRunFunc : public QObject
{
    Q_OBJECT

public:
    Q_INVOKABLE JsRunFunc(QObject* parent = nullptr);
    ~JsRunFunc();

    Q_INVOKABLE int callFunc(int number1, int number2);
};

其实现如下:

JsRunFunc::JsRunFunc(QObject* parent)
    :QObject(parent)
{
    qDebug() << __FUNCTION__;
}

JsRunFunc::~JsRunFunc()
{

}

int JsRunFunc::callFunc(int number1, int number2)
{
    qDebug() << __FUNCTION__;
    return number1 + number2;
}

如果想在JavaScript环境中,调用一个 JsRunFunc 的类对象。代码如下:

JsRunFunc* object = new JsRunFunc(this);
QJSValue jsObject = jsEngine->newQObject(object);
jsEngine->globalObject().setProperty("jsRunFuncObject", jsObject);
  • 使用函数 newQObject 创建一个类对象的代理对象 jsObject 。
  • 使用函数 globalObject().setProperty 设置全局对象属性 jsRunFuncObject 。
    这样就可以在JavaScript环境中,直接使用该对象了。
QJSValue value = jsEngine->evaluate("jsRunFuncObject.callFunc(10, 20)");
qDebug() << "CallFunc Result is " << value.toInt();

运行结果为:
CallFunc Result is 30

这里需要注意的是,如果JavaScript中想要使用C++类对象的函数,除了信号和槽函数,以及属性可以直接使用外,可以加宏 Q_INVOKABLE 修饰函数。

(3)添加类属性

如果想要在JavaScript环境中,添加类属性使用函数 newQMetaObject() 创建一个类的代理。

示例代码如下:

QJSValue jsMetaObject = jsEngine->newQMetaObject(&JsRunFunc::staticMetaObject);
jsEngine->globalObject().setProperty("JsRunFunc", jsMetaObject);
jsEngine->evaluate("var obj = new JsRunFunc; var result = obj.callFunc(100, 200); console.log(result)");

这里需要注意两点:

1. 类的构造函数中,必须使用宏 Q_INVOKABLE 修饰。
2. 类中必须使用宏 Q_OBJECT 。
此外,可以使用函数 installExtensions 安装一些扩展的功能。

jsEngine->installExtensions(QJSEngine::TranslationExtension | QJSEngine::ConsoleExtension);

QJSEngine(JavaScript引擎)

https://blog.csdn.net/kenfan1647/article/details/121353454

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值