Windows 下 QT 进程与 Node.js 进程通过共享内存通信

QT 进程共享内存可以借助 QT 提供的 QSharedMemory​​ 类实现,其是跨平台的。在 Windows 下,其基于 Windows File Mapping 技术实现内存共享。

NodeJS 进程需要通过编写 Addon(插件)的方式来访问 Window File Mapping API。编写 NodeJS Addon(插件)需要借助 node-addon-api 技术。

有关 Window File Mapping API,微软官方提供了 创建命名的共享内存 - Microsoft Learn 简单示例。

1 QT 写进程


#include <QCoreApplication>
#include <QSharedMemory>
#include <QDebug>
#include <cstring>
#include <QTimer>

int main(int argc, char *argv[])
{
    QCoreApplication a(argc, argv);

    // 创建 QSharedMemory 实例
    QSharedMemory sharedMemory;
    // 注意:设置本地 KEY
    sharedMemory.setNativeKey(QString::fromUtf8("MyTestSharedMemory"));
    // 创建共享内存,会自动调用 attach()
    if (!sharedMemory.create(1024, QSharedMemory::ReadWrite)) {
        qDebug() << "created failed";
        return -1;
    }
    qDebug() << "created successfully";
    // 绑定共享内存
    if (!sharedMemory.isAttached()) {
        qDebug() << "attached failed";
        return -1;
    }
    qDebug() << "attached successfully";

    // 定时写入动态数据
    QTimer timer;
    int count = 0;
    QObject::connect(&timer, &QTimer::timeout, [&]() {
       QString msg("hello data from shared memory!, index: ");
       msg.append(QString::number(count));
       const char * data_shm = msg.toStdString().c_str();
       // 向共享内存写入数据
       std::memcpy(sharedMemory.data(), data_shm, std::strlen(data_shm) + 1);
       qDebug() << "write data: " << data_shm;
       count += 1;
    });

    timer.start(1000); // 每秒更新一次

    return a.exec();
}

⚠️ 注意

由于此需求需要 QT 进程与 Node.js 进程通过共享通信,属于 QT 进程与非 QT 进程的交互场景,在创建 QSharedMemory​ 实例后,需要通过 setNativeKey()​ 方法设置本地 KEY。

2 Node.js 读进程


2.1 Node.js 读进程

node-filemap-buf Gitee 项目,其基于 node-addon-api 编写插件,通过调用 Window File Mapping 的 API 实现进程间内存共享。

  1. node-filemap-buf 项目克隆下来。将 node-filemap-buf\addon​ 目录下 addon.cc​、binding.gyp​、filemap.cc​、filemap.h​ 拷贝到你的 Node.js 工程根目录下。
  2. 使用 npm install -g node-gyp​ 命令全局安装 node-gyp​ 编译工具。
  3. 使用 npm install node-addon-api​ 命令本地安装 node-addon-api​ 依赖库
  4. 使用 node-gyp configure​ 命令配置工程,会生成 build​ 目录
  5. 使用 node-gyp build​ 编译工程,编译完成,会在 build/Release​ 目录下生成 addon.node​ 模块。

使用 build/release/addon.node​ 模块编写 Node.js 读进程代码:

var addon = require('./3rd/addon')
 
var mapName = "MyTestSharedMemory";
var bufSize = 1024;
var fileMap = new addon.FileMap();
 
var buf = fileMap.open(mapName,bufSize,0);
if(buf)
{
   console.log(`buf size=${buf.length}`);
   console.log(new String(buf));
}

2.2 Electron 读进程

过程完全参考 2.1 Node.js 读进程,但是对 node-filemap-buf 中的 filemap.cc​ 代码需要进行一点点修改,从而兼容 Electron 环境。

​filemap.cc​ 中

Napi::Value FileMap::create(const Napi::CallbackInfo& info)
{
   ...
   return Napi::Buffer<char>::New(env,(char*)pBuf, bufSize);
}

Napi::Value FileMap::open(const Napi::CallbackInfo& info)
{
   ...
   return Napi::Buffer<char>::New(env,(char*)buffer, bufSize);
}

的 return​ 语句与 Electron 不兼容。错误原因为:Napi::Buffer::New​ 方法直接将共享内存的指针暴露给 JavaScript。这种方式在标准 Node.js 环境中可能有效,但在 Electron 的 Node.js 环境中,外部缓冲区的管理受到限制,尤其是涉及共享内存时。

Electron 的 Node.js 环境可能会拒绝外部缓冲区的使用,因为它无法保证共享内存的生命周期和安全性。

为了解决上述问题,需要将 return​ 语句替换成:

// 创建一个新的缓冲区并复制数据
Napi::Buffer<char> resultBuffer = Napi::Buffer<char>::Copy(env, buffer, bufSize);

return resultBuffer;

参考链接:nodejs如何实现基于window File Mapping的进程间通信(IPC)_node addon发送ipc-优快云博客 

目前需要做一个课题《前端跨平台方案实现VCT客户端》,VCT是VIGI 配置工具,为解决客户购买大批量的VIGI设备,单个初始化太繁琐的问题而诞生。VIGI 配置工具部署在桌面客户端,目前仅支持Windows操作系统,为用户提供全面的设备管理、广泛的批量配置选项和可重复使用的模板,简化了安装人员的系统设置并减少了时间和成本。 目前VCT的系统架构是前端使用QT作为容器,提供桌面软件的系统级功能,基于Vue3的前端网页进行通信;后端使用Java技术栈。目前VCT仅支持Windows操作系统,考虑到对Mac、Linux操作系统的跨平台可复用性,催生了该课题《前端跨平台方案实现VCT客户端》。后端需要实现发现设备和管理设备的功能,发现设备通过广播udp实现,管理设备需要实现添加设备和设备的增删改查。已知流程是这样的,软件启动时开始搜寻局域网内的IPC、NVR、太阳能设备,并解析这些设备的型号、IP、端口号、MAC地址等信息,勾选设备并输入用户名和密码后,校验通过即可添加到设备列表。关于设备的增删改查,可以手动按照IP地址、端口号、用户名和密码来添加设备,可以多选删除设备,可以在上方输入框中根据设备的名称、MAC地址或IP进行查找,可以给设备重新分配IP地址。 现在要把qt容器更换为前端跨平台桌面软件框架, 诸如electron tauri flutter rn等,已知现在的团队全部都是js开发人员,所以学习rust成本太高,那tauri能否支持使用node来写后端呢?可以参考https://v2.tauri.app/zh-cn/learn/sidecar-nodejs/给出回答。目前综合考虑团队比较倾向于使用electron,但是又会面临内存占用和安装包过大的问题,请你对比这些前端跨平台桌面软件框架的优缺点,并说出技术选型的理由
最新发布
09-06
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值