Qt实现JavaScript与C++混合编程
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
测试例程一(用QScriptEngine相关类实现)
jsrunfunc.h
#ifndef JSRUNFUNC_H
#define JSRUNFUNC_H
#include <QObject>
#include <QDebug>
#include <QFile>
#include <QJSEngine>
#include <QJSValue>
class JsRunFunc : public QObject
{
Q_OBJECT
public:
// explicit JsRunFunc(QObject *parent = nullptr);
Q_INVOKABLE JsRunFunc(QObject *parent = nullptr);
~JsRunFunc();
Q_INVOKABLE double callFunc(double number1, double number2);
Q_INVOKABLE QString getSql(QString str);
signals:
};
#endif // JSRUNFUNC_H
jsrunfunc.cpp
#include "jsrunfunc.h"
JsRunFunc::JsRunFunc(QObject *parent) : QObject(parent)
{
qDebug()<< __FUNCTION__;
}
JsRunFunc::~JsRunFunc()
{
}
double JsRunFunc::callFunc(double number1, double number2)
{
qDebug()<< __FUNCTION__;
qDebug()<<"================callFunc===================";
return number1 + number2;
}
QString JsRunFunc::getSql(QString str)
{
qDebug()<<"=================getSql=================="<<str;
return "getsql value 123";
}
mainwindow.h
#ifndef MAINWINDOW_H
#define MAINWINDOW_H
#include <QMainWindow>
#include <QTextStream>
#include <QScriptEngine>
#include <QScriptValue>
#include "jsrunfunc.h"
QT_BEGIN_NAMESPACE
namespace Ui { class MainWindow; }
QT_END_NAMESPACE
class MainWindow : public QMainWindow
{
Q_OBJECT
public:
MainWindow(QWidget *parent = nullptr);
~MainWindow();
void initJsRunFunc(void);
void initJsRunFunc2(void);
private:
Ui::MainWindow *ui;
QJSEngine* jsEngine;
JsRunFunc* object;
};
#endif // MAINWINDOW_H
mainwindow.cpp
#include "mainwindow.h"
#include "ui_mainwindow.h"
MainWindow::MainWindow(QWidget *parent)
: QMainWindow(parent)
, ui(new Ui::MainWindow)
{
ui->setupUi(this);
// initJsRunFunc();
initJsRunFunc2();
}
MainWindow::~MainWindow()
{
delete ui;
}
void MainWindow::initJsRunFunc()
{
jsEngine = new QJSEngine(this);
// object = new JsRunFunc(this);
// QJSValue jsObject = jsEngine->newQObject(object);
// jsEngine->globalObject().setProperty("jsRunFuncObject", jsObject);
// QJSValue value = jsEngine->evaluate("jsRunFuncObject.callFunc(10.1, 20.1)");
// qDebug()<< "CallFunc Result is: " << value.toNumber();
QJSValue jsMetaObject = jsEngine->newQMetaObject(&JsRunFunc::staticMetaObject);
jsEngine->globalObject().setProperty("JsRunFunc", jsMetaObject);
QFile scriptFile(":/testJs.js");
if(!scriptFile.open(QIODevice::ReadOnly)){
qDebug()<<"open :/testJs.js failed!";
}
QTextStream out(&scriptFile);
QString contents = out.readAll();
scriptFile.close();
QJSValue value = jsEngine->evaluate("var x = 0.1; var y = 0.2; var obj = new JsRunFunc; var result = obj.callFunc(x, y); console.log(result);");
// qDebug()<<contents;
// qDebug()<< "CallFunc Result is: " << value.toNumber();
}
void MainWindow::initJsRunFunc2()
{
QFile scriptFile(":/testJs.js");
if(!scriptFile.open(QIODevice::ReadOnly)){
qDebug()<<"open :/testJs.js failed!";
}
QTextStream out(&scriptFile);
QString contents = out.readAll();
scriptFile.close();
QScriptEngine myEngine;
//调用类JsRunFunc的方法
object = new JsRunFunc(this);
QScriptValue qso = myEngine.newQObject(object);
myEngine.globalObject().setProperty("qso", qso);
QScriptValue value = myEngine.evaluate(contents);
qDebug()<< "show(1,2): " << value.toString();
qDebug()<< "-------------------------------------" ;
}
testJs.js
function show(x,y) {
var x = 0.1;
var y = 0.2;
var result = qso.callFunc(x, y);
var str = qso.getSql("abc");
var myObj = {name:"ningjingzhiyuan", age:xx, city:"shanghai"};
var myJSON = JSON.stringify(myObj);
return myJSON;
}
show(1,2);
测试结果
注意事项
目前测试,针对一个脚本只执行一个函数的情况,可以定义多个函数,但是只执行一个函数,否则执行的会有问题,尚未找到原因。
测试例程二(用QJSEngine相关类实现)
只复制不同地方的内容
void MainWindow::initJsRunFunc()
{
QFile scriptFile(":/testJs.js");
if(!scriptFile.open(QIODevice::ReadOnly)){
qDebug()<<"open :/testJs.js failed!";
}
QTextStream out(&scriptFile);
QString contents = out.readAll();
scriptFile.close();
jsEngine = new QJSEngine(this);
object = new JsRunFunc(this);
QJSValue jsObject = jsEngine->newQObject(object);
jsEngine->globalObject().setProperty("jsRunFuncObject", jsObject);
QJSValue value = jsEngine->evaluate(contents);
qDebug()<< "show(1,2): " << value.toString();
qDebug()<< "-------------------------------------" ;
}
testJs.js(用QJSEngine相关类实现)
function show(x,y) {
var x = 0.1;
var y = 0.2;
var result = jsRunFuncObject.callFunc(x, y);
var str = jsRunFuncObject.getSql("abc");
var myObj = {name:"ningjingzhiyuan", city:"shanghai"};
var myJSON = JSON.stringify(myObj);
return myJSON;
}
show(1,2);