Qt实现JavaScript与C++混合编程

Qt实现JavaScript与C++混合编程

  • JavaScript中调用C++
    • (1)添加全局对象属性
    • (2)添加类对象属性
    • (3)添加类属性
    • 这里需要注意两点:
  • QJSEngine(JavaScript引擎)
  • 测试例程一(用QScriptEngine相关类实现)
    • jsrunfunc.h
    • jsrunfunc.cpp
    • mainwindow.h
    • mainwindow.cpp
    • testJs.js
    • 测试结果
    • 注意事项
  • 测试例程二(用QJSEngine相关类实现)
    • testJs.js(用QJSEngine相关类实现)
    • 测试结果

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 
#include 
#include 
#include 
#include 

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 
#include 
#include 
#include 
#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()<
    //    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);

测试结果

Qt实现JavaScript与C++混合编程_第1张图片

注意事项

目前测试,针对一个脚本只执行一个函数的情况,可以定义多个函数,但是只执行一个函数,否则执行的会有问题,尚未找到原因。

测试例程二(用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);

测试结果

Qt实现JavaScript与C++混合编程_第2张图片

你可能感兴趣的:(Qt经验总结,javascript,qt,c++)