应用场景

  • 对接硬件(多用于对接第三方厂家硬件)
  • 使用系统 API 操作或扩展应用程序
  • js无法实现而由dll实现的其他功能

demo

git clone https://github.com/zhangxuelian/electron-vue-frame.git
cd electron-vue-frame
git fetch
git checkout electron-dll
npm install -g nrm 
nrm use taobao
// 使用管理员身份打开cmd终端:
npm install --global --production windows-build-tools
npm install
npm run dev
npm run build

注:出现报错请查看 异常情况处理

DLL介绍

Dynamic Link Library(动态链接库)的缩写,DLL是建立在客户/服务器通信的概念上,包含若干函数、类或资源的库文件,函数和数据被存储在一个DLL(服务器)上并由一个或多个客户导出而使用,这些客户可以是应用程序或者是其它的DLL。DLL库不同于静态库,在静态库情况下,函数和数据被编译进一个二进制文件(通常扩展名为*.LIB), Visual C++的编译器在处理程序代码时将从静态库中恢复这些函数和数据并把他们和应用程序中的其他模块组合在一起生成可执行文件。动态库每次在程序运行的时候去调用,而静态库需打包进exe,如果静态库有变动,则需要重新打包,而动态库不用。

前提条件

  • node.js64位不能对接32位dll,需对接64位dll;
  • 非C风格动态链接库目前node.js的生态社区暂不支持对接;
  • ffinode-ffi都停止维护,为了适配新版版本node(12.14.1+),需安装ffi-napi来进行对接;
  • ffi-napi在electron中需重编译,目前electron测试2.0.18和6.1.7均不支持重编译ffi-napi,9.1.1(最新版本)支持,8.4.1(9之前的最新发布版本)支持。

准备环境

electron项目(可使用一个简单框架进行测试)

git clone https://github.com/zhangxuelian/electron-vue-frame.git
// 或者 git clone https://gitee.com/zhangxuelian/electron-vue-frame.git
cd electron-vue-frame
npm install

注:该框架搭建过程可查看

安装依赖

  • 安装windows-build-tools(ffi-napi依赖ref-napi,这两者都需要依赖python2.7和c++编译工具,windows-build-tools为它们自动配置所需环境)
// 以管理员身份运行终端执行命令
npm install --global --production windows-build-tools
  • Node.js插件,用于使用纯JavaScript加载和调用动态库dll
npm install --save ffi-napi

webpack配置

如果在主进程中调用dll,则在主进程的配置中加上配置externals: [‘ffi-napi’]libraryTarget: ‘commonjs2’(渲染进程调用则在渲染进程的配置里加配置),如下所示:

let mainConfig = {
    entry: {
        ...
    },
    //这个模块包含原生 C代码,所以要在运行的时候再获取,而不是被webpack打包到bundle中
    externals: ['ffi-napi'],
    node: {
        ...
    },
    output: {
        // 入口起点的返回值将分配给 module.exports 对象,若不设,externals的对象无法使用
        libraryTarget: 'commonjs2',
        ...
    },
    plugins: [
        ...
    ],
    resolve: {
        ...
    },
    ...
}

调用DLL

这里以在主进程中调用为例,将测试的ZXLTest64.dll保存到项目的/extraResources/test目录下:

const ffi = require("ffi-napi");
const path = require("path");
var testdll = "";
if (process.env.NODE_ENV !== "development") {
	// 生产环境dll路径
    testdll = path.join(
        process.cwd(),
        "/resources/extraResources/test",
        "ZXLTest64.dll"
    );
} else {
	// 开发环境dll路径
    testdll = path.join(
        process.cwd(),
        "/extraResources/test",
        "ZXLTest64.dll"
    );
}
// 查看xx.dll库的xxx.h文件,这里的ZXLSDK_Init为调用函数名,
// 对应的数组第一个对象是返回对象,第二个对象为传参对象数组,result为调用dll的返回结果
var ZXLTest64 = new ffi.Library(testdll, {
	ZXLSDK_Init: ["int", ["int"]],
});
var result = ZXLTest64.ZXLSDK_Init(666);

打包配置

在package.json的build对象中,加入以下对象:

"build": {
    ...
    "extraResources": [
      {
        "from": "./extraResources/",
        "to": "extraResources"
      }
    ]
  }

执行和打包

最后结果查看项目示例:https://github.com/zhangxuelian/electron-vue-frame/tree/electron-dll

// 开发环境下构建
npm run dev
// 打包给生产环境
npm run build

异常情况处理

no such file or directory…

electron 调用 java 代码 electron 调用dll方法_webpack


解决方案:到node_modules下找到node-sass,删除该文件夹后,重新执行:npm install

Electron failed to install correctly

electron 调用 java 代码 electron 调用dll方法_git_02


解决方案:到node_modules下找到electron,删除该文件夹后,重新执行:npm install

找不到标识符(编译源文件 …)

electron 调用 java 代码 electron 调用dll方法_webpack_03


解决方案:升级node版本至12以上