GonaCli

一套快速使用 Golang 开发和构建生成 NodeJS Addon 扩展的开发工具

GONACLI 是一个快速使用 Golang 开发 NodeJS Addon 扩展的开发工具,开发者只需要专注在 Golang 的开发,无需关心与 NodeJS 的 Bridge 桥接层的实现,支持 JavaScript 同步调用和异步回调等。

⭐️ 如果能帮助到你,记得随手给点一个star。

  • https://github.com/wenlng/gonacli

  • QQ交流群1:885267905

兼容支持

  • Linux / Mac OS / Windows
  • NodeJS(12.0+)
  • Npm(6.0+)
  • Node-gyp(9.0+)
  • Go(1.14+)

使用 go 方式安装 gonacli 工具

安装前需要确保系统配置好了 GOPATH 及最终编译保存到 bin 目录的环境变量

Linux or Mac OS

# .bash_profile
export GOPATH="/Users/awen/go"# 配置 bin 目录,使用 golang 方式安装是必须的
export PATH="$PATH:$GOPATH:$GOPATH/bin"

Windows

# 打开系统环境变量设置
GOPATH: C:\awen\go
# 配置 bin 目录,使用 golang 方式安装是必须的
PATH: %GOPATH%\bin

开始安装

# linux or Mac OS
$ GOPROXY=https://goproxy.cn/,direct && go install github.com/wenlng/gonacli@latest# widow
$ set GOPROXY=https://goproxy.cn/,direct && go install github.com/wenlng/gonacli@latest$ gonacli version

Windows 环境编译

在 Windows 开发环境下需要安装 Go CGO 需要的 gcc/g++ 编译器,可以下载 "MinGW" 安装,配置好 MinGW/bin 的 PATH 环境变量即可,在命令行能够正常执行 gcc 。

$ gcc -v

Window 环境下还需要安装 NodeJS Addon 编译工具 node-gyp 依赖的 c/c++ 编译工具

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

gonacli 中的命令参数

1、generate

根据 goaddon 的配置生成对应 NodeJS Addon 相关的 Napi、C/C++ 桥接代码

# 默认将读取当前目录下的 goaddon.json 配置文件
$ gonacli generate# --config 参数指定配置文件
$ gonacli generate --config demoaddon.json

2、build

相当于 go build -buildmode=c-archive 命令,编译静态库

# 将 Go CGO 编译生成静态库
$ gonacli build# --config 参数指定配置文件
# --args 参数指定 go build 的参数,需要用 '' 引号包裹
$ gonacli build --args '-ldflags "-s -w"'

3、install

相当于 npm install 命令, 安装 NodeJS 需要的相关依赖

# --config 参数指定配置文件
$ gonacli install --config demoaddon.json

4、msvc

该命令只针对 window 环境下的兼容处理,需要 dlltool.exe 或 lib.exe (二选一)

1、"MinGW" 支持 "dlltool.exe" 工具

2、"Microsoft Visual c++ Build tools" 或 "Visual Studio" 的 "lib.exe" 工具

# --vs 参数表示使用 VS 的 "lib.exe" 工具,默认是 MinGW 的 "dlltool.exe" 工具
# --32x 参数表示支持 32 位的系统,默认 64 位
# --config 参数指定配置文件
$ gonacli msvc --config demoaddon.json

5、make

相当于 node-gyp configure && node-gyp build 命令,编译成最终的 NodeJS Addon 扩展

使用 make 命令请请确保系统已安装了 node-gyp 编译工具

# 编译
$ gonacli make# --args 参数指定 node-gyp build 的参数,例如调试 --debug 参数
$ gonacli make --args '--debug'

使用 Golang 快速开发 NodeJS Addon 的 Demo

Tip:请确保相关命令能正常使用,该 Demo 是在 Linux / Macos 环境下进行

# go
$ go version# node
$ node -v# npm
$ npm -v# node-gyp
$ node-gyp -v# gcc
$ gcc -v

1、新建配置文件

/goaddon.json

{"name": "demoaddon","sources": ["demoaddon.go"],"output": "./demoaddon/","exports": [{"name": "Hello","args": [{"name": "name","type": "string"}],"returntype": "string","jscallname": "hello","jscallmode": "sync"}]
}

2、编写 Golang 代码

/demoaddon.go

package main
import "C"// 注意://export xxxx 是必须的//export Hello
func Hello(_name *C.char) s *C.char {// 传入 string 类型,返回 string 类型name := C.GoString(_name)res := "hello"if len(name) > 0 {res += "," + name}return C.CString(res)
}

3、生成桥接的 Napi C/C++ 代码

# 生成保存到 ./demoaddon/ 目录下
$ gonacli generate --config ./goaddon.json

4、编译静态库

# 保存到 ./demoaddon/ 目录下
$ gonacli build

5、安装 Nodejs 相关依赖

# 保存到 ./demoaddon/ 目录下
$ gonacli install

6、编译 Nodejs Adddon

# 生成保存到 ./demoaddon/build 目录下
$ gonacli make

7、编写 js 测试文件

/demoaddon/test.js

const demoaddon = require('.')const name = "awen"
const res = demoaddon.hello(name)
console.log('>>> ', res)
$ node ./test.js
# >>> hello, awen

配置文件说明

{"name": "demoaddon",      // Nodejs Addon 扩展的名称      "sources": [              // go build 的文件列表,注意不能带有路径  "demoaddon.go"],"output": "./demoaddon/", // 最终输出目录路径"exports": [              // 导出的接口,生成 Addon 的 Napi、C/C++ 代码{"name": "Hello",      // 对应 Golang 的 "//export Hello" 接口名称,必须一致"args": [             // 传递的参数列表,参数型必须按照下面的类型表保持一致{                   // 参数要细心严谨,往往是因为配置的类型与 Golang 入口的不一致而导致编译失败"name": "name",   // 参数名称,但不能与当前参数列表中某一项重复"type": "string"  // 参数类型}],"returntype": "string",   // 返回给 JavaScript 的类型,没有 callback 类型"jscallname": "hello",    // JavaScript 调用的名称"jscallmode": "sync"      // sync 为同步执行、async 为异步执行(async值必须在args参数中指明 callback 类型参数)}]
}

类型对照表

-------- 请严格按照类型对照表 -------

Type Golang Args Golang Return JS / TS
int int32 C.int number
int32 int32 C.int number
int64 int64 C.longlong number
uint32 uint32 C.uint number
float float32 C.float number
double float64 C.double number
boolean bool bool boolean
string *C.char *C.char string
array *C.char *C.char Array
object *C.char *C.char Object
callback *C.char - Function

配置文件的 returntype 字段类型

returntype 字段没有 callback 类型

array 类型(当返回时存在多层时,在 returntype 中不推荐使用)

1、array 类型在 Golang 接收是字符串类型,需要配合使用 []interface{} 和 json.Unmarshal

2、array 类型在 Golang 返回时是 *C.char 类型,配合使用 json.Marshal

3、array 类型在 JavaScript 传递时是数组类型,但在接收时目前只支持一层,在 Golang 返回多层请使用字符串方式返回再使用 JavaScrpt 的 JSON.parse

object 类型(当返回时存在多层时,在 returntype 中不推荐使用)

1、object 类型在 Golang 接收是字符串 *C.char 类型,需要配合使用 [string]interface{} 和 json.Unmarshal

2、object 类型在 Golang 返回时是 *C.char 类型,配合使用 json.Marshal

3、object 类型在 JavaScript 传递时是对象类型,但在接收时目前只支持一层,在 Golang 返回多层请使用字符串方式返回再使用 JavaScrpt 的 JSON.parse

JavaScript 同步式调用

/goaddon.json

{"name": "demoaddon","sources": ["demoaddon.go"],"output": "./demoaddon/","exports": [{"name": "Hello","args": [{"name": "name","type": "string"}],"returntype": "string","jscallname": "hello","jscallmode": "sync"}]
}

2、编写 Golang 代码

/demoaddon.go

package main
import "C"//export Hello
func Hello(_name *C.char) s *C.char {// 传入 string 类型,返回 string 类型name := C.GoString(_name)res := "hello"ch := make(chan bool)// 当使用协程时,由于 JS 使用同步式调用,JS 进程会发生阻塞等待返回go func() {// 耗时任务处理time.Sleep(time.Duration(2) * time.Second)if len(name) > 0 {res += "," + name}   ch <- true}()<-chreturn C.CString(res)
}

3. Test

/test.js

const demoaddon = require('./demoaddon')const name = "awen"
const res = demoaddon.hello(name)
console.log('>>> ', res)

JavaScript 异步式回调

/goaddon.json

{"name": "demoaddon","sources": ["demoaddon.go"],"output": "./demoaddon/","exports": [{"name": "Hello","args": [{"name": "name","type": "string"},{"name": "cbs","type": "callback"}],"returntype": "string","jscallname": "hello","jscallmode": "async"}]
}

2、编写 Golang 代码

/demoaddon.go

package main
import "C"//export Hello
func Hello(_name *C.char, cbsFnName *C.char) s *C.char {// 传入 string 类型,返回 string 类型name := C.GoString(_name)res := "hello"ch := make(chan bool)// 当使用协程时,由于 JS 使用异步式调用,JS 进程不会发生阻塞,当返回值时会 JS callbackgo func() {// 耗时任务处理time.Sleep(time.Duration(2) * time.Second)if len(name) > 0 {res += "," + name}   ch <- true}()<-chreturn C.CString(res)
}

3. Test

/test.js

const demoaddon = require('./demoaddon')const name = "awen"
demoaddon.hello(name, funciton(res){console.log('>>> ', res)
})

LICENSE

MIT

一个快速使用 Golang 开发和构建生成 NodeJS Addon 扩展的开发工具相关推荐

  1. 【Groovy】Gradle 构建工具 ( 自动下载并配置构建环境 | 提供 API 扩展与开发工具集成 | 内置 Maven 和 Ivy 依赖管理 | 使用 Groovy 编写构建脚本 )

    文章目录 一.Gradle 自动下载并配置构建环境 二.Gradle 提供 API 扩展与开发工具集成 三.Gradle 内置 Maven 和 Ivy 依赖管理 四.Gradle 使用 Groovy ...

  2. 妙笔生花:一个易用、高效的文本生成开源库

    文本生成作为近年来自然语言处理中的热门领域,受到了学界和工业界的广泛关注.随着研究的不断深入,文本生成领域下的子任务和相应的模型越来越丰富,一些优秀的开源框架也纷纷涌现. 现有的开源文本生成库大致可分 ...

  3. web高德maker动画_Web Maker —我如何构建一个快速的离线前端游乐场

    web高德maker动画 by kushagra gour 由kushagra gour Web Maker -我如何构建一个快速的离线前端游乐场 (Web Maker - How I built a ...

  4. Stark 组件:快速开发神器 —— 自动生成 URL

    说道 Stark 你是不是不会想到他--Tony Stark,超级英雄钢铁侠,这也是我的偶像. 不过我们今天要开发的 Stark 组件,倒是跟他的人工智能助手 JARVIS 有些类似,是帮助我们快速开 ...

  5. 深入浅出教你做一个快速开发平台

    快速开发平台,重点在于快,要快无非就是两种手段: 1.生成代码 2.重用模块 详细看如下的分支图 就第一种情况生成代码来说,是每个快速开发平台必备的,基本上所有的快速开发平台都能生成CRUD,从jsp ...

  6. 无需训练 RNN 或生成模型,如何编写一个快速且通用的 AI “讲故事”项目?

    作者 | Andre Ye 译者 | 弯月,责编 | 郭芮 头图 | CSDN 下载自视觉中国 出品 | CSDN(ID:CSDNnews) 以下为译文: 这段日子里,我们都被隔离了,就特别想听故事. ...

  7. java fields是_一个快速生成R2.java中fields的插件

    一个快速生成R2.java中fields的插件 项目地址:github.com/JeasonWong/- 介绍 在子 module 中使用 ButterKnife 时,如果想使用 ButterKnif ...

  8. .NET Core实战项目之CMS 第十一章 开发篇-数据库生成及实体代码生成器开发

    上篇给大家从零开始搭建了一个我们的ASP.NET Core CMS系统的开发框架,具体为什么那样设计我也已经在第十篇文章中进行了说明.不过文章发布后很多人都说了这样的分层不是很合理,什么数据库实体应该 ...

  9. Dendron: 一款支持双链、Git 管理、本地存储,专为开发人员构建的开源个人知识管理工具...

    公众号关注 「奇妙的 Linux 世界」 设为「星标」,每天带你玩转 Linux ! Dendron 是一个开源的.本地优先的.基于 markdown 的笔记工具,它是专为开发人员构建的个人知识管理解 ...

最新文章

  1. 清华 词向量库_word2vec 构建中文词向量
  2. go加载python_人生苦短我用python(02)动态加载模块-Go语言中文社区
  3. PHP中Cookie的使用---添加/更新/删除/获取Cookie 及 自动填写该用户的用户名和密码和判断是否第一次登陆...
  4. Anaconda安装及第一个py程序
  5. 如何优雅的实现DML批量操作
  6. 第七十九期:阿里程序员感慨:码农们过去暴富有多轻松,现在赚钱就有多辛苦
  7. ruby 集合 分组_在Ruby中打印集合的元素
  8. C++子对象和堆对象
  9. 函数返回结构体指针_9.3 结构体指针
  10. 去掉Win7资源管理器左侧不需要的项目
  11. Android 布局左中右布局
  12. VR+教育 虚拟现实(VR)智慧教室整体解决方案
  13. HenCoder Plus L02—— 编码、加密、Hash
  14. 企业为什么需要一套固定资产管理系统
  15. 多多自走棋服务器不稳定,《多多自走棋》将登陆Epic平台 PC版数据将与移动版互通...
  16. 瞬变抑制二极管TVS原理简介
  17. 计算机视觉c刊论文,摄影外文文献 摄影核心期刊参考文献哪里找
  18. DDD—快速理解聚合根、实体、值对象的区别和联系
  19. 如何修改图片的dpi?图片怎么调dpi?
  20. 如何绘制程序流程图?绘制程序流程图工具介绍及功能讲解

热门文章

  1. 混得不好,就别去思考
  2. 荣耀畅玩7C挑战红米5 Plus,千元手机档的王者对决
  3. Echarts离线地图开发--实现web端 初始化世界地图,其他国家钻取到行政区,中国钻取到省市区的展示
  4. 奇数阶矩阵,横竖斜加起来都相等算法(罗伯法幻方)
  5. 云电竞的服务器,斗鱼云游戏平台发布:无客户端玩游戏 网友:真就云玩家了呗...
  6. 基于Prompt的MLM文本分类
  7. C#基础之结构体枚举数组
  8. 一建公共课推荐老师详解
  9. c语言五子棋怎么判断五子连珠,五子棋 输赢判断算法
  10. 华硕笔记本如何进入U盘启动