依星源码资源网,依星资源网

 找回密码
 立即注册

QQ登录

只需一步,快速开始

查看: 14|回复: 0

Electron9.x +vue+ffi-napi 调用Dll动态链接库

[复制链接] 主动推送

8576

主题

8628

帖子

9513

积分

管理员

Rank: 9Rank: 9Rank: 9

积分
9513
发表于 5 天前 | 显示全部楼层 |阅读模式
Electron9.x +vue+ffi-napi 调用Dll动态链接库.
本文主要介绍在 Electron9.x 中,使用ffi-napi,ref-array-napi,ref-napi 加载 Windows 动态链接库,并在Vue 渲染进程中使用。使用过程中会遇到一系列的坑,本文将会一一解决,并解释原因。如有同行兄弟遇到此问题可以借鉴。

这里列出所使用的环境:

Visual Studio 2017
NodeJS  v12.17.0 (x64)
node-gyp v7.0.0
Python 2.7.15
Electron :9.1.0
@vue/cli 4.4.6
vue-cli-plugin-electron-builder : 2.0.0-rc.4
ffi-napi : 3.0.1
ref-napi : 2.0.3
ref-array-napi : 1.2.1
ref-struct-napi : 1.1.1
1. 先自己开发一个DLL文件备用
非本文重点,熟悉的朋友可以略过。在这个DLL中,分别开发了三种情况的C函数:

A. 参数为基本数据类型
B. 参数为指针
C. 参数为指向数组的指针
A比较简单,而B和C 涉及到 参数为指针的情况,函数内部可以修改指针指向的内存,函数运行完毕之后,外部内存中的值将会被修改。相当于输出参数,使用JS调用的时候涉及到内存共享问题。

使用 Visual Studio 2017  开发DLL步骤如下:

1.1 新建项目

Electron9.x +vue+ffi-napi 调用Dll动态链接库

Electron9.x +vue+ffi-napi 调用Dll动态链接库

配置编译为 64 位,因为我的 NodeJS为 64 位

Electron9.x +vue+ffi-napi 调用Dll动态链接库

Electron9.x +vue+ffi-napi 调用Dll动态链接库


1.2 头文件
MyDllDemo.h  IDE 自动生成了这个文件,并自动创建了 CMyDllDemo (类), nMyDllDemo(全局变量),fnMyDllDemo (函数), 这些我们都不需要,将它们删除,重新定义:

  1. // `extern "C"`意味着: 被 extern "C" 修饰的变量和函数是按照 C 语言方式编译和链接的
  2. extern "C"
  3. {
  4.     // MYDLLDEMO_API 是上面定义的宏,其实就是  __declspec(dllexport)
  5.     // 参数和返回值都是基本数据类型
  6.     MYDLLDEMO_API int add(int a, int b);

  7.     // 使用指针修改函数外部数据作为返回值
  8.     MYDLLDEMO_API void addPtr(int a, int b,int* z);

  9.     // 外部传入数组的首地址,函数负责初始化数组数据
  10.     // array为 数组首地址, length 为数组长度
  11.     MYDLLDEMO_API void initArray(int* array,int length);
  12. }
复制代码
1.3 源文件
MyDllDemo.cpp  删除 生成的代码后,实现代码如下:

  1. #include "pch.h"
  2. #include "framework.h"
  3. #include "MyDllDemo.h"
  4. MYDLLDEMO_API int add(int a, int b) {
  5.     return a + b;
  6. }

  7. // 使用指针修改函数外部数据作为返回值
  8. MYDLLDEMO_API void addPtr(int a, int b, int* z) {
  9.     *z = a + b;
  10. }

  11. // 外部传入数组的首地址,函数负责初始化数组数据
  12. MYDLLDEMO_API void initArray(int* array,int length) {
  13.     for (int i = 0; i < length;i++,array++) {
  14.         *array = 100 + i; // 假设数组长度为4, 则程序运行完毕后结果为[100,101,102,103]
  15.     }
  16. }
复制代码
1.4 编译生成DLL文件

Electron9.x +vue+ffi-napi 调用Dll动态链接库

Electron9.x +vue+ffi-napi 调用Dll动态链接库

Electron9.x +vue+ffi-napi 调用Dll动态链接库

Electron9.x +vue+ffi-napi 调用Dll动态链接库


这个 MYDLLDEMO.dll 文件就是我们要在 Node JS中调用的DLL文件。
注意这里编译出来的dll是64位的,NodeJS也应该是64位的。
2 新建NodeJS项目
假设项目目录在 G:/node_ffi_napi_demo
  1. cd g:\node_ffi_napi_demo
  2. npm init -y
复制代码
此时生成了一个 package.json文件
2.1 环境准备
在安装依赖之前,先做些准备工作。因为 安装 ffi_napi 依赖的时候,需要有编译环境,否则会因为无法编译而报错。
  1. # 添加配置,被保存到了 <windows用户主目录>/.npmrc  配置文件中
  2. npm set registry https://registry.npm.taobao.org/
  3. npm set ELECTRON_MIRROR https://npm.taobao.org/mirrors/electron/
  4. npm set SASS_BINARY_SITE http://npm.taobao.org/mirrors/node-sass
  5. npm set PYTHON_MIRROR http://npm.taobao.org/mirrors/python
  6. # 非必须,备以后使用
  7. npm i chromedriver -g --chromedriver_cdnurl=http://npm.taobao.org/mirrors/chromedriver
  8. # 使用Vue Cli创建vue项目的时候会用到
  9. npm i -g node-sass
  10. # NodeJS 编译 C/C++ 依赖用到
  11. npm i -g node-gyp  

  12. #windows 编译工具,需要用管理员身份运行 PowerShell,如果 报错 Could not install Visual Studio Build Tools. 则到 C:\Users\wuqing\.windows-build-tools 目录下 手工进行安装,安装成功后在执行上面的命令
  13. npm i -g --production windows-build-tools  

  14. # 安装Python,注意必须是 2.7 版本,安装后并设置环境变量
复制代码
解决网络下载问题:以管理员身份打开 windows host文件,( C:\Windows\System32\drivers\etc\hosts ),加入如下映射:
  1. 52.216.164.171 github-production-release-asset-2e65be.s3.amazonaws.com
  2. 52.216.99.59 github-production-release-asset-2e65be.s3.amazonaws.com
  3. 54.231.112.144 github-production-release-asset-2e65be.s3.amazonaws.com
  4. 54.231.88.43 github-production-release-asset-2e65be.s3.amazonaws.com
  5. 52.216.8.107 github-production-release-asset-2e65be.s3.amazonaws.com
复制代码
更新DNS: ipconfig /flushdns
以上如果首次安装,会比较慢,需要耐心等待
2.2 安装依赖
  1. cd g:\node_ffi_napi_demo
  2. # https://www.npmjs.com/package/ffi-napi
  3. # 安装这个依赖的时候,会自动使用 node-gyp 进行编译
  4. npm i -S ffi-napi
  5. ...其它输出省略
  6. > ffi-napi@3.0.1 install G:\node_ffi_napi_demo\node_modules\ffi-napi
  7. > node-gyp-build
  8. ...
  9. + ffi-napi@3.0.1
  10. added 10 packages from 58 contributors in 39.928s
复制代码
安装 ref-napi 的时候,只从仓库中下载了源代码,并没有自动执行编译,需要手工执行编译,先执行 node-gyp configure
  1. npm i -S ref-napi
  2. cd node_modules\ref-napi\
  3. node-gyp configure  //配置
  4. # 下面是控制台输出内容
  5. gyp info it worked if it ends with ok
  6. gyp info using node-gyp@7.0.0
  7. gyp info using node@12.17.0 | win32 | x64
  8. gyp info find Python using Python version 2.7.15 found at "C:\Users\xxxxx\.windows-build-tools\python27\python.exe"
  9. gyp info find VS using VS2017 (15.9.28307.1216) found at:
  10. ... 省略输出
  11. gyp info spawn args   '-Dmodule_root_dir=G:\\node_ffi_napi_demo\\node_modules\\ref-napi',
  12. gyp info spawn args   '-Dnode_engine=v8',
  13. gyp info spawn args   '--depth=.',
  14. gyp info spawn args   '--no-parallel',
  15. gyp info spawn args   '--generator-output',
  16. gyp info spawn args   'G:\\node_ffi_napi_demo\\node_modules\\ref-napi\\build',
  17. gyp info spawn args   '-Goutput_dir=.'
  18. gyp info spawn args ]
  19. gyp info ok
复制代码
在执行编译命令:node-gyp build
  1. node-gyp build

  2. # 以下是输出内容
  3. gyp info it worked if it ends with ok
  4. gyp info using node-gyp@7.0.0
  5. gyp info using node@12.17.0 | win32 | x64
  6. gyp info spawn C:\Program Files (x86)\Microsoft Visual Studio\2017\BuildTools\MSBuild\15.0\Bin\MSBuild.exe
  7. gyp info spawn args [
  8. gyp info spawn args   'build/binding.sln',
  9. gyp info spawn args   '/clp:Verbosity=minimal',
  10. gyp info spawn args   '/nologo',
  11. gyp info spawn args   '/p:Configuration=Release;Platform=x64'
  12. gyp info spawn args ]
  13. 在此解决方案中一次生成一个项目。若要启用并行生成,请添加“/m”开关。
  14.   nothing.c
  15.   win_delay_load_hook.cc
  16.   nothing.vcxproj -> G:\node_ffi_napi_demo\node_modules\ref-napi\build\Release\\nothing.lib
  17.   binding.cc
  18.   win_delay_load_hook.cc
  19.     正在创建库 G:\node_ffi_napi_demo\node_modules\ref-napi\build\Release\binding.lib 和对象 G:\node_ffi_napi_demo\node_modules\ref-napi\build\Release\binding.exp
  20.   正在生成代码
  21.   All 571 functions were compiled because no usable IPDB/IOBJ from previous compilation was found.
  22.   已完成代码的生成
  23.   binding.vcxproj -> G:\node_ffi_napi_demo\node_modules\ref-napi\build\Release\\binding.node
  24. gyp info ok
复制代码
安装 ref-array-napi 和 ref-struct-napi  ,因为它们只是纯JS包,并没有本地 C代码,所以无需 node-gyp 编译
  1. npm i -S ref-array-napi ref-struct-napi
复制代码
3. 使用ffi-napi 调用Dll
将前面生成的 DLL文件拷贝到NodeJS项目根目录下,然后新建一个 index.js 作为nodejs 程序入口:

Electron9.x +vue+ffi-napi 调用Dll动态链接库

Electron9.x +vue+ffi-napi 调用Dll动态链接库


index.js
  1. const ffi = require('ffi-napi')
  2. var ref = require('ref-napi')
  3. var ArrayType = require('ref-array-napi')
  4. const path = require('path')

  5. // 映射到C语言 int数组类型
  6. var IntArray = ArrayType(ref.types.int)

  7. // 加载 DLL文件,无需写扩展名,将DLL中的函数映射成JS方法
  8. const MyDellDemo = new ffi.Library(path.resolve('MYDLLDEMO'), {
  9.   // 方法名必须与C函数名一致
  10.   add: [
  11.     'int', // 对应 C函数返回类型
  12.     ['int', 'int'] // C函数参数列表
  13.   ],
  14.    // 使用 ffi中内置类型的简写类型
  15.   addPtr: ['void', ['int', 'int', 'int*']],
  16.    // IntArray 是上面通过 ArrayType 构建出来的类型
  17.   initArray: ['void', [IntArray, 'int']]
  18. })

  19. // 调用add 方法
  20. const result = MyDellDemo.add(1, 2)
  21. console.log(`add method result of 1 + 2 is: ` + result)

  22. // 调用addPtr 方法
  23. // 使用Buffer类在C代码和JS代码之间实现了内存共享,让Buffer成为了C语言当中的指针。
  24. // C函数使用指针操作函数外部的内存,所以首先需要 分配一个int类型的内存空间 第一个参数为 C语言数据类型,第二个参数为 默认值
  25. var intBuf = ref.alloc(ref.types.int, 100)
  26. console.log('addPtr 调用前数据>>', ref.deref(intBuf)) //获取指向的内容
  27. MyDellDemo.addPtr(2, 2, intBuf) // 调用函数,传递指针
  28. console.log('addPtr 调用后数据>>', ref.deref(intBuf))

  29. // 调用initArray 方法
  30. // IntArray 是前面使用ref-napi 和 ref-array-napi 库创建的数据类型,数组的长度为 8
  31. // 这里一定要分配内存空间,否则 函数内的指针无法操作内存
  32. let myArray = new IntArray(8)
  33. MyDellDemo.initArray(myArray, 8)
  34. console.log('初始化数组执行结果:')
  35. for (var i = 0; i < myArray.length; i++) {
  36.   console.log(myArray[i])
  37. }
复制代码
要点:
package.json 加入启动脚本
  1. {
  2.   "name": "node_ffi_napi_demo",
  3.   "version": "1.0.0",
  4.   "description": "",
  5.   "main": "index.js",
  6.   "scripts": {
  7.     "start": "node index.js"
  8.   },
  9.   "keywords": [],
  10.   "author": "",
  11.   "license": "ISC",
  12.   "dependencies": {
  13.     "ffi-napi": "^3.0.1",
  14.     "ref-array-napi": "^1.2.1",
  15.     "ref-napi": "^2.0.3",
  16.     "ref-struct-napi": "^1.1.1"
  17.   }
  18. }
复制代码
启动程序执行:
  1. npm start
  2. # 下面是输出
  3. > node_ffi_napi_demo@1.0.0 start G:\node_ffi_napi_demo
  4. > node index.js

  5. add method result of 1 + 2 is: 3
  6. addPtr 调用前数据>> 100
  7. addPtr 调用后数据>> 4
  8. 初始化数组执行结果:
  9. 100
  10. 101
  11. 102
  12. 103
  13. 104
  14. 105
  15. 106
  16. 107
复制代码
4. 在 Electron 9.x 中使用
以上代码在 NodeJS  v12.17.0 (x64) 环境下能够执行成功。下面尝试在 Electron9.1.0 中能够执行成功
4.1 安装Electron 9
  1. npm i electron@9.1.0 -D
复制代码
Electron9 被安装到了 node_modules目录中了,node 提供了 npx命令来方便执行 node_modules下的可执行脚本,稍后在 package.json中添加启动脚本。
4.2 编写main.js 来启动 Electron
main.js
  1. const { app, BrowserWindow } = require('electron')
  2. app.on('ready', function createWindow() {
  3.   // 创建窗口
  4.   let win = new BrowserWindow({
  5.     width: 800,
  6.     height: 600,
  7.     webPreferences: {
  8.       nodeIntegration: true // Node 中的API可以在渲染进程中使用
  9.     }
  10.   })

  11.   // 渲染进程中的web页面可以加载本地文件
  12.   win.loadFile('index.html')
  13.   // 记得在页面被关闭后清除该变量,防止内存泄漏
  14.   win.on('closed', function () {
  15.     win = null
  16.   })
  17. })

  18. // 页面全部关闭后关闭主进程,这里在不同平台可能有不同的处理方式,这里不深入研究
  19. app.on('window-all-closed', () => {
  20.   app.quit()
  21. })
复制代码
前面写的 index.js  将会被引入到 index.html中, index.html文件:
  1. <!DOCTYPE html>
  2. <html lang="en">
  3.   <head>
  4.     <meta charset="UTF-8" />
  5.     <meta name="viewport" content="width=device-width, initial-scale=1.0" />
  6.     <title>Document</title>
  7.   </head>
  8.   <body>
  9.     请点击菜单,打开开发者工具,查看控制台输出
  10.     <script src="index.js"></script>
  11.   </body>
  12. </html>
复制代码
在package.json中添加启动脚本
  1.   "scripts": {
  2.     "start": "node index.js",
  3.     "electron": "npx electron main.js"
  4.   },
复制代码
上面添加了一个名称为 electron的启动脚本,使用 npx命令启动 node_modules 中的 electron.exe, 并指定 main.js 作为入口文件

Electron9.x +vue+ffi-napi 调用Dll动态链接库

Electron9.x +vue+ffi-napi 调用Dll动态链接库
view > Toggle Developer Tools  可以打开开发者工具,Dll调用的结果在控制台上输出。


5. 在Vue Electron  builder 项目中调用DLL
在实际的 Vue Electron项目中调用 Dll 的时候,会遇到一些问题,通过配置可以解决这些问题。我在实际使用的过程中,刚开始遇到了很多问题,一度以为 NodeJS  12.X  和  Electron 9.x 与  ffi-napi  不兼容。有了前面的实验,可以可定的是不存在兼容性问题,通过在 vue.config.js文件中配置,这些问题都可以解决。
5.1 安装@vue/cli
  1. npm i -g @vue/cli@4.4.6
  2. cd g:
  3. vue create electron_vue_ffi_demo
  4. # 选择默认选项
  5. Vue CLI v4.4.6
  6. ? Please pick a preset:
  7.   .preset (node-sass, babel, router, eslint)
  8.   element (node-sass, babel, router, eslint)
  9. > default (babel, eslint)
  10.   Manually select features
  11.   
  12.   # 等待安装
复制代码


5.2 安装 electron-builder 插件
  1. cd electron_vue_ffi_demo
  2. vue add electron-builder
  3. # 我在写这篇文章的时候,electron-builder 只提示到 Electron 9.0.0 版本,先选择这个版本,然后重新安装 9.1.0

  4.   ^7.0.0
  5.   ^8.0.0
  6. > ^9.0.0
复制代码
我们的目标是实验 Electron 9.1.0 ,所以先卸载  9.0.0,然后再安装 9.1.0
  1. npm uninstall electron
  2. npm i electron@9.1.0 -D
复制代码
5.3 安装ffi-napi,ref-napi ,ref-array-napi,ref-struct-napi  依赖
这里使用一条命令进行安装
  1. npm i ffi-napi ref-napi ref-array-napi ref-struct-napi -S
复制代码
ffi-napi 会自动调用windows编译工具进行编译,但是 ref-napi 不会,还需要手动执行 node-gyp 命令进行编译
  1. cd node_modules\ref-napi\
  2. node-gyp configure
  3. node-gyp build

  4. cd g:\electron_vue_ffi_demo
复制代码
5.4 去掉 electron-devtools-installer 的安装
项目 package.json文件中已经添加了启动脚本:
  1.   "scripts": {
  2.     "serve": "vue-cli-service serve",
  3.     "build": "vue-cli-service build",
  4.     "lint": "vue-cli-service lint",
  5.     "electron:build": "vue-cli-service electron:build",
  6.     "electron:serve": "vue-cli-service electron:serve",
  7.     "postinstall": "electron-builder install-app-deps",
  8.     "postuninstall": "electron-builder install-app-deps"
  9.   }
复制代码
使用命令 npm run electron:serve 来启动 Electron窗口,发现启动非常慢,最后输出:
  1. Failed to fetch extension, trying 4 more times
  2. Failed to fetch extension, trying 3 more times
  3. Failed to fetch extension, trying 2 more times
  4. Failed to fetch extension, trying 1 more times
复制代码
这是因为 默认添加的 background.js 文件中,做了 electron-devtools-installer 插件安装,因为网络原因我们无法在google应用商店下载到插件,所以这里直接在代码中去掉这部分的安装。
在 background.js 中注释掉:
  1. import installExtension, { VUEJS_DEVTOOLS } from 'electron-devtools-installer'
复制代码
将 app.on方法中的if 语句块注释掉
  1. app.on('ready', async () => {
  2.   // if (isDevelopment && !process.env.IS_TEST) {
  3.   //   // Install Vue Devtools
  4.   //   try {
  5.   //     await installExtension(VUEJS_DEVTOOLS)
  6.   //   } catch (e) {
  7.   //     console.error('Vue Devtools failed to install:', e.toString())
  8.   //   }
  9.   // }
  10.   createWindow()
  11. })
复制代码
再次执行 npm run electron:serve 发现很快启动
5.5 允许渲染进程集成NodeJS
background.js  代码中默认nodeIntegration 是为false,通过查看 vue-cli-plugin-electron-builder 插件文档 得知,可以通过在 vue.config.js 配置文件中进行配置:
  1. module.exports = {
  2.   pluginOptions: {
  3.     electronBuilder: {
  4.       nodeIntegration: true
  5.     }
  6.   }
  7. }
复制代码
5.6 DLL文件
将上面的DLL文件拷贝到项目中。首先在 项目根目录下创建一个 resources文件,这个文件中把 DLL文件作为资源文件放入到项目中。 这里我将DLL编译出了32位和64 位两个文件,都放到了resources目录中。实际运行的时候,可以根据Nodes 是 32位还是 64 位来加载对应的DLL文件。

Electron9.x +vue+ffi-napi 调用Dll动态链接库

Electron9.x +vue+ffi-napi 调用Dll动态链接库
5.7 编写MyDLL  JS模块
在 src 目录下编写 MyDll.js 文件,在这个文件中 加载 DLL文件,并导出为JS 对象方法。
src/MyDll.js 。 这里直接拿上个项目中的 index.js 稍作改动,添加了 32 ,64 架构判断,并将DLL调用用JS进行了封装后导出
  1. const ffi = require('ffi-napi')
  2. var ref = require('ref-napi')
  3. var ArrayType = require('ref-array-napi')
  4. const path = require('path')
  5. let { arch } = process // x64

  6. //默认加载 32位 DLL
  7. let dllFilePath = path.resolve('resources/MYDLLDEMO_x32')
  8. if (arch === 'x64') {
  9.   dllFilePath = path.resolve('resources/MYDLLDEMO_x64')
  10. }

  11. // 映射到C语言 int数组类型,并导出
  12. const IntArray = ArrayType(ref.types.int)

  13. // 加载 DLL文件,无需写扩展名,将DLL中的函数映射成JS方法
  14. // 导出为JS方法
  15. const MyDellDemo = new ffi.Library(dllFilePath, {
  16.   // 方法名必须与C函数名一致
  17.   add: [
  18.     'int', // 对应 C函数返回类型
  19.     ['int', 'int'] // C函数参数列表
  20.   ],
  21.   addPtr: ['void', ['int', 'int', 'int*']],
  22.   initArray: ['void', [IntArray, 'int']]
  23. })

  24. module.exports = {
  25.   add(x, y) {
  26.     return MyDellDemo.add(x, y)
  27.   },
  28.   addPtr(x, y) {
  29.     var intBuf = ref.alloc(ref.types.int, 100)
  30.     MyDellDemo.addPtr(x, y, intBuf)
  31.     return ref.deref(intBuf)
  32.   },
  33.   initArray(len) {
  34.     let myArray = new IntArray(len)
  35.     MyDellDemo.initArray(myArray, len)
  36.     let result = []
  37.     for (var i = 0; i < len; i++) {
  38.       result.push(myArray[i])
  39.     }
  40.     return result
  41.   }
  42. }
复制代码
5.8 尝试在主进程中调用
在 background.js 文件中,加载 MyDLL 模块并调用它. 在文件末尾处加入代码:
  1. import { add, addPtr, initArray } from './MyDll'
  2. // 调用add 方法
  3. const result = add(1, 2)
  4. console.log(`add method result of 1 + 2 is: ` + result)
  5. // 调用addPtr
  6. console.log('addPtr 调用后数据>>', addPtr(2, 2)) // 调用函数,传递指针

  7. // 调用initArray 方法
  8. let myArray = initArray(4)
  9. console.log('初始化数组执行结果:')
  10. for (var i = 0; i < myArray.length; i++) {
  11.   console.log(myArray[i])
  12. }
复制代码
启动 npm run electron:serve, 发现报告错误:

Electron9.x +vue+ffi-napi 调用Dll动态链接库

Electron9.x +vue+ffi-napi 调用Dll动态链接库
  1. App threw an error during load
  2. Error: No native build was found for platform=win32 arch=x64 runtime=electron abi=80 uv=1 libc=glibc
  3.     at Function.load.path (webpack:///./node_modules/node-gyp-build/index.js?:56:9)
  4.     at load (webpack:///./node_modules/node-gyp-build/index.js?:21:30)
  5.     at eval (webpack:///./node_modules/ref-napi/lib/ref.js?:8:111)
  6.     at Object../node_modules/ref-napi/lib/ref.js (G:\electron_vue_ffi_demo\dist_electron\index.js:1764:1)
  7.     at __webpack_require__ (G:\electron_vue_ffi_demo\dist_electron\index.js:20:30)
  8.     at eval (webpack:///./node_modules/ffi-napi/lib/ffi.js?:7:13)
  9.     at Object../node_modules/ffi-napi/lib/ffi.js (G:\electron_vue_ffi_demo\dist_electron\index.js:635:1)
  10.     at __webpack_require__ (G:\electron_vue_ffi_demo\dist_electron\index.js:20:30)
  11.     at eval (webpack:///./src/MyDll.js?:1:13)
  12.     at Object../src/MyDll.js (G:\electron_vue_ffi_demo\dist_electron\index.js:2080:1)
复制代码


发现是因为 找不到本地编译模块导致。查询 vue-cli-plugin-electron-builder 插件文档https://nklayman.github.io/vue-cli-plugin-electron-builder/guide/guide.html#table-of-contents, 发现这样一句话:

Electron9.x +vue+ffi-napi 调用Dll动态链接库

Electron9.x +vue+ffi-napi 调用Dll动态链接库


上文中说要将 本地的包配置到 webpack的 externals(外部扩展)中指定。引用webpack官方文档中的话:
防止将某些 import 的包(package)打包到 bundle 中,而是在运行时(runtime)再去从外部获取这些扩展依赖(external dependencies)。
所以在 vue.config.js文件中做如下配置:
  1. module.exports = {
  2.   pluginOptions: {
  3.     electronBuilder: {
  4.       nodeIntegration: true,
  5.       //因为这两个模块中包含原生 C代码,所以要在运行的时候再获取,而不是被webpack打包到bundle中
  6.       externals: ['ffi-napi', 'ref-napi']
  7.     }
  8.   }
  9. }
复制代码
再次执行后,发现控制台输出正常:


  1. INFO  Launching Electron...
  2. add method result of 1 + 2 is: 3
  3. addPtr 调用后数据>> 4
  4. 初始化数组执行结果:
  5. 100
  6. 101
  7. 102
  8. 103
复制代码
5.9 在渲染进程中使用
App.vue
  1. <template>
  2.   <div id="app">
  3.     <button @click="exeAdd">执行add方法</button> {{ addResult }}
  4.     <hr />
  5.     <button @click="exeAddPtr">执行addPtr方法</button> {{ addPtrResult }}
  6.     <hr />
  7.     <button @click="exeInitArray">执行initArray方法,初始化数组</button>
  8.     {{ initArrayResult }}
  9.     <hr />
  10.   </div>
  11. </template>

  12. <script>
  13. import { add, addPtr, initArray } from './MyDll'
  14. export default {
  15.   data() {
  16.     return {
  17.       addResult: null,
  18.       addPtrResult: null,
  19.       initArrayResult: null
  20.     }
  21.   },
  22.   methods: {
  23.     exeAdd() {
  24.       this.addResult = add(100, 200)
  25.     },
  26.     exeAddPtr() {
  27.       this.addPtrResult = addPtr(2, 2)
  28.     },
  29.     exeInitArray() {
  30.       let len = 4
  31.       this.initArrayResult = initArray(len)
  32.       console.log('初始化数组执行结果:', this.initArrayResult)
  33.     }
  34.   }
  35. }
  36. </script>
复制代码

Electron9.x +vue+ffi-napi 调用Dll动态链接库

Electron9.x +vue+ffi-napi 调用Dll动态链接库


现在执行正常。
5.10 打包
执行打包脚本:
  1. npm run electron:build
复制代码

Electron9.x +vue+ffi-napi 调用Dll动态链接库

Electron9.x +vue+ffi-napi 调用Dll动态链接库
执行exe文件后:

Electron9.x +vue+ffi-napi 调用Dll动态链接库

Electron9.x +vue+ffi-napi 调用Dll动态链接库
这个问题是因为找不到DLL文件。原因是 打包的时候,没有将项目中的dll文件拷贝到最终生成的dist_electron\win-unpacked  文件夹中。这同样需要在 vue.config.js 文件中做配置:
  1. module.exports = {
  2.   pluginOptions: {
  3.     electronBuilder: {
  4.       nodeIntegration: true,
  5.       //因为这两个模块中包含原生 C代码,所以要在运行的时候再获取,而不是被webpack打包到bundle中
  6.       externals: ['ffi-napi', 'ref-napi'],
  7.       builderOptions: {
  8.         extraResources: {
  9.           // 拷贝静态文件到指定位置,否则打包之后出现找不到资源的问题.将整个resources目录拷贝到 发布的根目录下
  10.           from: 'resources/',
  11.           to: './'
  12.         }
  13.       }
  14.     }
  15.   }
  16. }
复制代码
再次打包后. 在 win-unpacked\resources 中就能找到 dll文件了

Electron9.x +vue+ffi-napi 调用Dll动态链接库

Electron9.x +vue+ffi-napi 调用Dll动态链接库





相关帖子

扫码关注微信公众号,及时获取最新资源信息!下载附件优惠VIP会员5折;永久VIP免费
您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

免责声明:
1、本站提供的所有资源仅供参考学习使用,版权归原著所有,禁止下载本站资源参与商业和非法行为,请在24小时之内自行删除!
2、本站所有内容均由互联网收集整理、网友上传,并且以计算机技术研究交流为目的,仅供大家参考、学习,请勿任何商业目的与商业用途。
3、若您需要商业运营或用于其他商业活动,请您购买正版授权并合法使用。
4、论坛的所有内容都不保证其准确性,完整性,有效性,由于源码具有复制性,一经售出,概不退换。阅读本站内容因误导等因素而造成的损失本站不承担连带责任。
5、用户使用本网站必须遵守适用的法律法规,对于用户违法使用本站非法运营而引起的一切责任,由用户自行承担
6、本站所有资源来自互联网转载,版权归原著所有,用户访问和使用本站的条件是必须接受本站“免责声明”,如果不遵守,请勿访问或使用本网站
7、本站使用者因为违反本声明的规定而触犯中华人民共和国法律的,一切后果自己负责,本站不承担任何责任。
8、凡以任何方式登陆本网站或直接、间接使用本网站资料者,视为自愿接受本网站声明的约束。
9、本站以《2013 中华人民共和国计算机软件保护条例》第二章 “软件著作权” 第十七条为原则:为了学习和研究软件内含的设计思想和原理,通过安装、显示、传输或者存储软件等方式使用软件的,可以不经软件著作权人许可,不向其支付报酬。若有学员需要商用本站资源,请务必联系版权方购买正版授权!
10、本网站如无意中侵犯了某个企业或个人的知识产权,请来信【站长信箱312337667@qq.com】告之,本站将立即删除。
郑重声明:
本站所有资源仅供用户本地电脑学习源代码的内含设计思想和原理,禁止任何其他用途!
本站所有资源、教程来自互联网转载,仅供学习交流,不得商业运营资源,不确保资源完整性,图片和资源仅供参考,不提供任何技术服务。
本站资源仅供本地编辑研究学习参考,禁止未经资源商正版授权参与任何商业行为,违法行为!如需商业请购买各资源商正版授权
本站仅收集资源,提供用户自学研究使用,本站不存在私自接受协助用户架设游戏或资源,非法运营资源行为。
 
在线客服
点击这里给我发消息 点击这里给我发消息 点击这里给我发消息
售前咨询热线
312337667

微信扫一扫,私享最新原创实用干货

QQ|免责声明|依星资源网 ( 鲁ICP备2021043233号-3 )|网站地图

GMT+8, 2024-7-17 00:43

Powered by Net188.com X3.4

邮箱:312337667@qq.com 客服QQ:312337667(工作时间:9:00~21:00)

快速回复 返回顶部 返回列表