最近有个新项目,其中有录屏功能,需要调用 C++ Node 插件。
调试阶段初期,C++ 同事很快就发过来插件 Zip,里面包含 plugin.node 文件。
简单,写个 app.js,直接引入插件,然后打印出来。
const plugin = require("./Plugin/DemoPlugin.node");
console.log(plugin);
用 node 执行 node app.js
没想到直接报错:
DemoPlugin.node is not a valid Win32 application.
这个提示就有迷惑性,语义上来说,是指这个插件不是 32 位的,但 C++ 同事明确地说,这就是 32位,想要 64位还暂时给不了呢。
其实是因为我本地安装的 Node 是 64 位,用 64 位的 Node 启动 32 位的 node 插件,就会出现上面的错误。
怎么看自己本地安装的 Node 是 64 位还是 32 位呢?
参考 stackoverflow.com/questions/2…
node -p "process.arch"
可以看到我的本地输出 x64,如果是 32 位,则是显示 ia32,注意不是 x86。
顺便了解一下,关于 x86、x86-64和IA-32、IA-64 的区别
然后我又下载了 32 位版本的 Node,又发现了新的报错,NODE_MODULE_VERSION 版本不匹配。
Error: The module '\Plugin\DemoPlugin.node'
was compiled against a different Node.js version using
NODE_MODULE_VERSION 87. This version of Node.js requires
NODE_MODULE_VERSION 108. Please try re-compiling or re-installing
the module (for instance, using `npm rebuild` or `npm install`).
at Module._extensions..node (node:internal/modules/cjs/loader:1310:18)
at Module.load (node:internal/modules/cjs/loader:1089:32)
at Module._load (node:internal/modules/cjs/loader:930:12)
at Module.require (node:internal/modules/cjs/loader:1113:19)
at require (node:internal/modules/cjs/helpers:103:18)
at Object.<anonymous> (C:\Users\fujinxiang\Downloads\node-v18.14.0-win-x86\app.js:1:16)
at Module._compile (node:internal/modules/cjs/loader:1226:14)
at Module._extensions..js (node:internal/modules/cjs/loader:1280:10)
at Module.load (node:internal/modules/cjs/loader:1089:32)
at Module._load (node:internal/modules/cjs/loader:930:12) {
code: 'ERR_DLOPEN_FAILED'
}
刚开始不清楚 Node 版本对应的 NODE_MODULE_VERSION,直接把 node-v18.14.0,node-v16.18.1,node-v15.14.0,node-v14.9.0 的 32 位版本都下载下来,都会报错。
后来发现在 nodejs.org/zh-cn/downl… 有 Node 版本和 NODE_MODULE_VERSION 对应关系。
Node v14.x 对应 NODE_MODULE_VERSION 83,Node v15.x 对应 NODE_MODULE_VERSION 88。
根本没有 NODE_MODULE_VERSION 是 87 的 Node 版本啊!
难怪 node-v15.14.0,node-v14.9.0 的 32 位都不行。
后来 electron程序,如何理解NODE_MODULE_VERSION? 提供思路。
NODE_MODULE_VERSION 87 这个版本号,其实是来自 Electron。
验证看看,写一个 version.js,内容如下
console.log(process.versions.modules);
执行 electron version.js
,输出 87
所以,这个 DemoPlugin.node,其实是 C++ 同事基于 Electron v12.0.16 版本编译的,复用了此前某项目的环境。
可以看的这个版本的 Electron 有点旧了,而目前新项目中选择的 Electron 版本是 v21.3.0,对应的 Node 版本是 v16.16.0,而 NODE_MODULE_VERSION 是 109。
所以,接下来,我需要下载 32 位 Electron v21.3.0 版本,并要求 C++ 同事重新编译对应版本的 DemoPlugin.node 插件。
而编译 node 插件,需要对应版本的 node-gyp,但这个 node-gyp 只能从 Electron 去下载,Node 官网并没有对应版本。
网上会找到一些文章告诉我们这样下载,target 后面是 Electron 对应的版本
node-gyp rebuild --target=4.1.5 --dist-url=https://atom.io/download/electron
但其实这个写法已经过时了,因为 Electron 已经从 atom-shell 更名很久了。
正确的写法应该下面这样,参考 www.electronjs.org/docs/latest…
node-gyp rebuild --target=21.3.0 --arch=ia32 --dist-url=https://electronjs.org/headers
此处一定要注意保证网络情况,可能有必要科学上网,否则可能会遇到类似下面这样的错误。
gyp WARN install got an error, rolling back install
gyp ERR! configure error
gyp ERR! stack Error: EPERM: operation not permitted, unlink 'C:\Users\~\AppData\Local\node-gyp\Cache\21.3.0\arm64\node.lib'
gyp ERR! System Windows_NT 10.0.22000
看起来是权限不足,其实就是网络不行。
执行 node-gyp rebuild --target=21.3.0 --arch=ia32 --dist-url=https://electronjs.org/headers
之后,会在 \AppData\Local\node-gyp\Cache 目录下看到 21.3.0 目录,其中就包含重新编译 node 插件需要的依赖文件。
至此,问题终于解决。