下拉即可刷新...

探索如何利用 Golang 语言开发 NodeJS 的 Addon 扩展支持

使用 Golang 语言的 CGO 支持编写好处理代码后编译成动态库,通过 C++ 结合 NodeJS 的 NAPI 为中间桥梁,调用 Golang 导出的相关 API,并返回对应数据等,再提供给 NodeJS 调用,此 DEMO 实例作为扩展实现的第一步抛砖引玉。

点击生成页面海报

支持二维码扫描,以及短链接,分享到好友更方便 ~~

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条 )

0/300

暂无 “评论” 相关数据

已经到底了