NodeJS 的扩展实现方式有多种,它默认的最佳实现是 C/C++ 。
这里探索的是如何使用 Golang 的 CGO 支持 来编写扩展处理的实现,然后编译为动态库,导出对应C/C++支持调用的天然API,中间使用 C/C++ NAPI 来作为桥梁,处理 Nodejs 与 Golang 的数据传递。
首先,在开始前先确保安装了 nodejs 和包依赖管理工具npm(或者pnpm、cnpm、yarn都可以),这里演示使用的是npm。
初始化扩展库的工程目录
mkdir goaddon
cd goaddon
npm init
安装编译工具 node-gyp 和扩展库需要的 bindings、node-addon-api 依赖
npm i node-gyp bindings node-addon-api -S
Golang 代码处理实现
在当前工程目录下新建 goaddon.go 文件
package main
import "C"
//export Sum
func Sum(x, y float64) float64 {
return x + y
}
// 尽量保留
func main() {
// ...
}
Golang编写完成后,编译成静态库提供API给C/C++调用
go build -buildmode c-archive -o goaddon.a goaddon.go
C/C++ 结合 NAPI 编写与 Golang 静态库数据传递的调用及处理
在当前工程目录下新建 goaddon.cc 文件
#include <napi.h>
#include <string>
#include "goaddon.h"
using namespace Napi;
std::string sum(double s, double t) {
// 调用 Golang 提供的API函数
double res = Sum(s, t);
return std::to_string(res);
}
Napi::String Method(const Napi::CallbackInfo& info) {
Napi::Env env = info.Env();
// NodeJS 调用进入后,处理和转换成 C/C++ 支持的数据类型
double arg1 = info[0].As<Number>().DoubleValue();
double arg2 = info[1].As<Number>().DoubleValue();
std::string demo = sum(arg1, arg2);
return Napi::String::New(env, demo);
}
Napi::Object Init(Napi::Env env, Napi::Object exports) {
// 暴露相关函数给 Nodejs 调用
exports.Set(Napi::String::New(env, "sum"),
Napi::Function::New(env, Method));
return exports;
}
NODE_API_MODULE(goaddon, Init)
编写 node-gyp 编译配置文件
在当前工程目录下新建 binding.gyp 文件
{
"targets": [
{
"target_name": "goaddon",
"cflags!": [ "-fno-exceptions" ],
"cflags_cc!": [ "-fno-exceptions" ],
"sources": [ "goaddon.cc" ],
"include_dirs": [
"<!@(node -p \"require('node-addon-api').include\")"
],
'defines': [ 'NAPI_DISABLE_CPP_EXCEPTIONS' ],
"libraries": [
"../goaddon.a"
],
}
]
}
使用 node-gyp 工具编译成 .node 扩展
编译完成后在当前目录下会生成一个 build 目录存放 node 扩展
npx node-gyp configure
npx node-gyp build
编写库的入口文件
在当前工程目录下新建 index.js 文件
const goaddon = require('bindings')('goaddon')
// 暴露给 JavaScript 调用
module.exports = {
sum: goaddon.sum
}
在 package.json 添加当前包的入口和gyp
{
"name": "goaddon",
// ....
"main": "index.js",
"gyp": true
}
编写测试文件
在当前工程目录下新建 test.js 文件
// 表示导入当前 index.js
const goaddon = require('.')
// 开启调用扩展库的API
console.log(goaddon.sum(2.0, 5.0))
// >>> 7.000000
传递复杂类型数据通信及函数回调等处理实现后续更新...
发表评论 ( 0条 )
暂无 “评论” 相关数据