likes
comments
collection
share

不懂electron-vue的前端小白,如何实现与c++多线程交互

作者站长头像
站长
· 阅读数 56

前言:

哈喽,掘友们,大家好呀!最近在业余的时间里,尝试跟朋友一起做了一款客户端产品,小编负责前端开发设计,后台逻辑呢是与c++和python交互。这是小编从未接触过的领域,从一开始的调研,到测试实现,真的是废了好大的功夫,可以说是煞费苦心。不过,庆幸的是,自己没有接触到的领域,可以实践在其中去学习,去了解这一系列的知识,当然,学到就是赚到。

开始调研

调研目的: 实现 Electron+vue 桌面应用开发与 C++ 交互通信,调用 C++ 代码 调研方法:通过 Node.js 插件 node-ffi-napi 调用 C++ 编写的Dll动态库,实现调用 C++ 代码

开发版本

  • node v14.15.1
  • vue v2.6.14
  • electron v13.6.9
  • node-gyp v9.3.1
  • ffi-napi v4.0.3

上边是小编开发过程中使用到的依赖包以及版本号

环境准备

搭建环境,安装node-gyp、windows-build-tools

  1. 全局安装 node-gyp
npm install node-gyp -g
  1. 全局安装 windows-build-tools
npm install windows-build-tools -g

注意安装 windows-build-tools 时 python 版本必须为 2.7

使用ffi-napi

  1. 进入项目目录,安装ffi-napi
npm install ffi-napi --save
  1. 封装 C++ 方法文件

新建 callC.js 文件,放在 src 的 utils 目录下

引入 ffi-napi,path 模块,加载 C 方法,并导出

// 引入模块
const ffi = require('ffi-napi')
const path = require('path')
// 通过 ffi.Library 加载 dll 文件 加载 C++ 方法
const Dll = ffi.Library(path.resolve('resources/dll/MyDLL.dll'), {
    Add: ['float', ['float', 'float']],
    Hello: ['string', []],
    StrLength: ['int', ['string']]
})
// 导出Dll状态库
export default Dll;
  1. 在 Electron + vue 中使用 C 方法

再使用组件中引入封装的文件

// 引入封装的callC文件
import Dll from '../../utils/callC'

mounted() {
    console.log('fii.Library Hello result:', Dll.Hello())
    console.log('fii.Library Add result:', Dll.Add(1, 2))
    console.log('fii.Library Add result:', Dll.StrLength('hello world'))
}

不懂electron-vue的前端小白,如何实现与c++多线程交互 调用 C 成功!

这个时候我们的dll代码已经调用成功了,但是如果c++中要求有回调函数,持续返回信息给我们,这时候就需要多线程,否则就会导致项目进程阻塞,页面卡死,无法使用。

web worker 多线程交互

使用多线程的目的

开发 electron + vue 桌面系统时, 使用 ffi-napi 调用 C++,实现交互。但是 C++ 代码如果进行循环式回调,会导致页面卡死,是因为JavaScript是单线程应用。也就是说,所有的任务都只能在一个线程上进行,如果要进行下一步,就只能等前边的任务执行完毕,才可以执行到下一步,如果计算量特别大,又或者说C++的回调函数一直在进行中,那么我们接下来的任务就无法进行,就会导致页面卡死、无法操作。

什么是web worker ?

Web worker 是为web 内容在后台线程中提供的一种简单的方法。线程可以执行任务而不干扰用户操作界面。创建web worker 可以将消息发送到创建它的JavaScript代码,通过消息发布到该代码指定的时间处理程序中,从而实现异步多线程调用函数。

如何在 vue + element 中使用 web worker 多线程开发

  1. 设置 Electron 的 webPreferences 中的 nodeIntegrationInWorker 选项设置为 true
const win = new BrowserWindow({
  webPreferences: {
    nodeIntegrationInWorker: true
  }
})
  1. 安装 worker-loader
npm i worker-loader  
  1. 编写 子线程 worker.js 文件
onmessage = function (e) {
    console.log(e);
    // 此处的e就是主线程通过postMessage 传递过来的数据
    // 在此处进行数据分析,数据操作
    postMessage(str);  // 向主线程传递信息
}
  1. 在项目目录中 引入worker.js文件 ./worker.js是文件路径信息,引入直接写在 worker-loader! 后边
import Worker from 'worker-loader!./worker.js'
  1. 在 vue 中使用
methods:{
    WorkerOne() {
      // 新建一个线程
      worker= new Worker()
      // 线程之间通过postMessage进行通信
      worker.postMessage(0)
      // 监听message事件
      worker.addEventListener('message', (e) => {
          // 关闭线程
          console.log('1------' + e.data);
      })
      worker.terminate()   // 立刻终止一个运行中的 worker  终止线程
    },
}
mounted() {
    this.WorkerOne()
}

关于如何生成共享 worker, 官方文档给出了详细的介绍和说明。 developer.mozilla.org/zh-CN/docs/…

结尾

项目目前还在进行中,小编也是在不断地学习,electron官方文档中也是有很多的api,随后项目结束后我也会更新下文,关于我如何从头搭建electron—vue的项目,如何实现与c++、与python交互也会与大家分享。总而言之,学习永无止境,要试着向自己从未接触到的领域学习,这样会更直观的看到自己的不足,要学习的方向。

转载自:https://juejin.cn/post/7231057317332467767
评论
请登录