electron加载第三方c++库走过的坑

image.png


文章目录



前言

在node的程序中,如果有大数据量的计算,处理起来比较慢,可以用C来处理,然后通过回调(callback的形式),返回给node.
那么编写好的C
组件如何可以在node.js环境中调用呢.
Node.js 插件是用 C++ 编写的动态链接共享对象,可以使用 require() 函数加载到 Node.js 中,且像普通的 Node.js 模块一样被使用. 它们主要用于为运行在 Node.js 中的 JavaScript 与 C/C++ 库之间提供接口.


node.js如何编写c++组件

以官方Hello World” 示例是一个简单的插件,用 C++ 编写,如下代码:

module.exports.hello = () => 'world';

创建hello.cc文件

// hello.cc
#include <node.h>

namespace demo {

using v8::FunctionCallbackInfo;
using v8::Isolate;
using v8::Local;
using v8::Object;
using v8::String;
using v8::Value;

void Method(const FunctionCallbackInfo<Value>& args) {
  Isolate* isolate = args.GetIsolate();
  args.GetReturnValue().Set(String::NewFromUtf8(isolate, "world"));
}

void init(Local<Object> exports) {
  NODE_SET_METHOD(exports, "hello", Method);
}

NODE_MODULE(NODE_GYP_MODULE_NAME, init)

}  // namespace demo

注意 所有的 Node.js 插件必须导出一个如下模式的初始化函数:

void Initialize(Local<Object> exports);
NODE_MODULE(NODE_GYP_MODULE_NAME, Initialize)
  • NODE_MODULE 后面没有分号,因为它不是一个函数(详见 node.h)
  • module_name 必须匹配最终的二进制文件名(不包括 .node 后缀)
  • 在 hello.cc 示例中,初始化函数是 init,插件模块名是 addon

构建

当源代码已被编写,它必须被编译成二进制 addon.node 文件.
要做到这点,需在项目的顶层创建一个名为 binding.gyp 的文件,它使用一个类似 JSON 的格式来描述模块的构建配置.
该文件会被 node-gyp(一个用于编译 Node.js 插件的工具)使用

{
  "targets": [
    {
      "target_name": "addon",
      "sources": [ "hello.cc" ]
    }
  ]
}

需要直接使用 node-gyp 的开发者可以使用 npm install -g node-gyp 命令进行安装

但 binding.gyp 文件已被创建,使用 node-gyp configure 为当前平台生成相应的项目构建文件.
这会在 build/ 目录下生成一个 Makefile 文件(在 Unix 平台上)或 vcxproj 文件(在 Windows 上).


编译

调用 node-gyp build 命令生成编译后的 addon.node 的文件.
它会被放进项目文件 build/Release/ 内.


调用

编译后的二进制插件的文件扩展名是 .node(而不是 .dll 或 .so).
require() 函数用于查找具有 .node 文件扩展名的文件,并初始化为动态链接库.

// hello.js
const addon = require('./build/Release/addon');

console.log(addon.hello());
// 打印: 'world'

electron调用c++组件

Electron是GitHub开发的一个开源框架.它允许使用Node.js和Chromium完成桌面GUI应用程序的开发.
我们可以看出 electron 已经集成了前端js环境(Chromium)和后端js环境(Node.js).

那么上面我们已经看到node.js可以直接通过 node-gyp编译c库转化成node.js可以直接交互的二进制 .node 编译文件.
所以我们一样可以理解electron框架下可以自己直接加载 node-gyp编译的c
库.

可能遇到的坑


NODE_MODULE_VERSION不匹配

这是因为你当前使用的node.js版本与electron内置的node.js版本不一致,
当你更新系统的node.js版本与electron一致时,编译后启动客户端,发现还是有这样的问题,提示NODE_MODULE_VERSION不匹配.
这可能的原因是node.js版本一致,但是内置的v8引擎版本不一致导致.

如何填坑?
如下解决方案,前提是系统成功安装 node.js环境,python2.7环境,node-gyp环境.
如果你是windows系统:
强烈建议使用如下方式安装vs环境及python环境

npm install --global --production windows-build-tools

electron-rebuild重新编译c++库

在electron环境下编译c++库,确保node.js版本,v8引擎版本和使用环境一模一样.
注意
electron-rebuild 安装到开发环境中,install时必须指定 -dev模式
安装:

npm install --save-dev electron-rebuild

执行:

./node_modules/.bin/electron-rebuild

编译成功后,build/release 文件夹下有编译生成的 .node 文件,用于electron require此二进制文件.


node-gyp编译时指定系统及electron版本

另外一种方法是使用node-gyp编译时指定系统参数:
编译:

node-gyp rebuild --target=5.0.13 --dist-url=https://atom.io/download/electron

注意 5.0.13 是我的electron版本
然后 build/release 目录下生成的 .node 文件就可以在electron中require使用了.

出自:electron加载第三方c++库走过的坑

回到顶部