1. C++ 插件
1.1 前端成长曲线:
刚参加工作的程序员都倾向做后端开发,大家都觉得前端比较简单,后期成长曲线比较缓慢。
能在日常工作做项目中,就可以成长当然最好了,进入一个好的平台对成长帮助很大。但是很多人就没那么幸运了,这时候更多时候需要我们做一个有心人,持续学习。
底层基础很重要,计算机基础还是需要经常查看。
1.2 万物归于c:
- 高级语言都是运行在操作系统之上,本身只能运行在用户态。
- 操作系统管理计算机的资源,运行在内核态,操作系统是c写的,也就是c/c这样的高级语言可以直接与操作系统交互。
- 高级语言需要使用系统资源,只能通过系统调用。
- 在node、java我们都可以看到native方法,也就是c写的,除了c语言执行比较快,主要还是它们不能直接系统调用
- node、java虚拟机本质也是操作系统一个应用程序,具备解释执行node、java语言
1.3 node与c
-
Native Addon
一个 Native Addon 在 Nodejs 的环境里就是一个二进制文件, 这个文件是由低级语言, 比如 C 或 C++实现, 我们可以像调用其他模块一样 require() 导入 Native Addon
Native Addon 与其他.js 的结尾的一样, 会暴露出
module.exports或者exports对象, 这些被封装到 node 模块中的文件也被成为 Native Module(原生模块) .
-
ABI Application Binary Interface 应用二进制接口
Native Addon 与 Nodejs 进行通信的桥梁. ABI 定义了二进制文件(尤其是so文件)如何运行在相应的系统平台上,从使用的指令集,内存对其到可用的系统函数库。简单来说,通过abi接口,c/c++ 文件可以转化为运行在各种平台上的so文件。
-
插件
是用 C++ 编写的动态链接共享对象
Nodejs 可以动态加载 C 和 C++的 DLL 文件, 并且在 js 程序中使用其 API
c++插件提供了 JavaScript 和 C/C++ 库之间的接口。
require()函数可以将插件加载为普通的 Node.js 模块
实现插件有三种选择:Node-API、nan 或直接使用内部 V8、libuv 和 Node.js 库
-
构建原生插件的 API
-
node-addon-api:
#include <napi.h>
-
Node-API
#include <node_api.h>
2.插件编写
- 需要全局安装
yarn global add node-gyp, 因为还依赖于 Python, (GYP 全称是 Generate Your Project, 是一个用 Python 写成的工具) - 构建命令: node-gyp configure build
- binding.gyp
- c ++ 实现
- js引用
2.1 binding.gyp
{
"targets": [
{
"target_name": "addon",
"sources": [ "addon.cc" ]
}
]
}
2.2 c ++ 实现
// addon.cc
#include <node.h>
namespace demo {
using v8::Exception;
using v8::FunctionCallbackInfo;
using v8::Isolate;
using v8::Local;
using v8::Number;
using v8::Object;
using v8::String;
using v8::Value;
// 这是 "add" 方法的实现
// 输入参数使用
// const FunctionCallbackInfo<Value>& args 结构传入
void Add(const FunctionCallbackInfo<Value>& args) {
Isolate* isolate = args.GetIsolate();
// 检查传入的参数数量。
if (args.Length() < 2) {
// 抛出传回 JavaScript 的错误
isolate->ThrowException(Exception::TypeError(
String::NewFromUtf8(isolate,
"Wrong number of arguments").ToLocalChecked()));
return;
}
// 检查参数类型
if (!args[0]->IsNumber() || !args[1]->IsNumber()) {
isolate->ThrowException(Exception::TypeError(
String::NewFromUtf8(isolate,
"Wrong arguments").ToLocalChecked()));
return;
}
// 执行操作
double value =
args[0].As<Number>()->Value() + args[1].As<Number>()->Value();
Local<Number> num = Number::New(isolate, value);
// 设置返回值
// (使用传入的 FunctionCallbackInfo<Value>&)
args.GetReturnValue().Set(num);
}
void Init(Local<Object> exports) {
NODE_SET_METHOD(exports, "add", Add);
}
NODE_MODULE(NODE_GYP_MODULE_NAME, Init)
}
2.3 js引用
调用 node-gyp build 命令生成编译后的 addon.node 文件。 这将被放入 build/Release/ 目录。
const addon = require('./build/Release/addon');
console.log('This should be eight:', addon.add(3, 5));
关于打包的跨平台
通常在发布模块的时候, 不会把
build文件夹算在内, 但是.node文件是放在里面的. 而且.node文件之前说了, 依赖于系统和架构, 如果是使用 macOS 打包的.node肯定是不能在 windows 上使用的. 那么怎么实现兼容性呢? 没错, 每次在用户安装的时候都重新按照对应硬件配置build 一遍, 也就是使用node-gyp rebuild
参考链接:
nodejs.cn/api/addons.…
juejin.cn/post/684490…
欢迎关注我的前端自检清单,我和你一起成长