English | 中文
GONACLI is a development tool that quickly uses Golang to develop NodeJS Addon. You only need to concentrate on the development of Golang, and you don't need to care about the implementation of the bridge layer. It supports JavaScript sync calls and async callbacks.
⭐️ If it helps you, please give a star.
- Linux
- Mac OS
- Windows
- Linux / Mac OS / Windows
- NodeJS(12.0+)
- Npm(6.0+)
- Node-gyp(9.0+)
- Go(1.14+)
Ensure that the system is configured with GOPATH environment variables before installation
Linux or Mac OS
# .bash_profile
export GOPATH="/Users/awen/go"
# set bin dir
export PATH="$PATH:$GOPATH:$GOPATH/bin"
Window
# set system path
GOPATH: C:\awen\go
# set bin dir
PATH: %GOPATH%\bin
Install
$ go install github.com/wenlng/gonacli@latest
$ gonacli version
In the Windows OS environment, you need to install the gcc/g++
compiler support required by Go CGO, download the MinGW
installation, configure the PATH
environment variable of MinGW/bin
, and execute gcc
normally on the command line.
$ gcc -v
When compiling Node Addon in the Windows OS environment, you also need to install the build tool that node-gyp
and depends on.
$ npm install --global node-gyp
$ npm install --global --production windows-build-tools
Generate bridge code related to NodeJS Addon according to the configuration of goaddon
# By default, it reads the goaddon in the current directory Json configuration file
$ gonacli generate
# --config: Specify Profile
$ gonacli generate --config demoaddon.json
Same as the go build - buildmode=c-archive
command, compile the library
# Compile to generate library
$ gonacli build
# --args: Specify the args of go build
# --config: Specify Profile
$ gonacli build --args '-ldflags "-s -w"'
Same as the npm install
, Install NodeJS dependencies.
# Install dependencies
gonacli install
# --config: Specify Profile
$ gonacli install --config demoaddon.json
Select dlltool.exe
in the Windows OS environment or lib.exe
1.dlltool.exe
of MinGW
2.lib.exe
of Microsoft Visual c++ Build tools
or Visual Studio
$ gonacli msvc
# --vs: use VS "lib.exe", default is "dlltool.exe" of MinGW
# --32x: Supports 32-bit OS,default 64.
# --config: Specify Profile
$ gonacli msvc --config demoaddon.json
Same as the node-gyp configure && node-gyp build
command,Compile NodeJS Addon
Please ensure that the node gyp compiler has been installed on the system before using the "make" command
Before using the "--npm-i" arg, ensure that the system has installed the npm package dependency management tool
# --args: Specify the parameters of node-gyp build,for example "--debug"
$ gonacli make --args '--debug'
Tip:Ensure that relevant commands can be used normally, This is an demo under Linux/OS environment.
# go
$ go version
# node
$ node -v
# npm
$ npm -v
# node-gyp
$ node-gyp -v
/goaddon.json
{
"name": "demoaddon",
"sources": [
"demoaddon.go"
],
"output": "./demoaddon/",
"exports": [
{
"name": "Hello",
"args": [
{
"name": "name",
"type": "string"
}
],
"returntype": "string",
"jscallname": "hello",
"jscallmode": "sync"
}
]
}
/demoaddon.go
package main
import "C"
// notice://export xxxx is necessary
//export Hello
func Hello(_name *C.char) *C.char {
// args string type,return string type
name := C.GoString(_name)
res := "hello"
if len(name) > 0 {
res += "," + name
}
return C.CString(res)
}
# Save to the "./demoaddon/" directory
$ gonacli generate --config ./goaddon.json
# Save to the "./demoaddon/" directory
$ gonacli build
# Save to the "./demoaddon/build" directory
$ gonacli install
# Save to the "./demoaddon/build" directory
$ gonacli make
/demoaddon/test.js
const demoaddon = require('.')
const name = "awen"
const res = demoaddon.hello(name)
console.log('>>> ', res)
$ node ./test.js
# >>> hello, awen
{
"name": "demoaddon", // Name of Nodejs Addon
"sources": [ // File list of go build,Cannot have path
"demoaddon.go"
],
"output": "./demoaddon/", // Output directory path
"exports": [ // Exported interface, generating the Napi and C/C++ code of Addon
{
"name": "Hello", // The name of the "//export Hello" interface corresponding to Golang must be consistent
"args": [ // The parameter type of the passed parameter list must be consistent with the type table
{
"name": "name",
"type": "string"
}
],
"returntype": "string", // The type returned to JavaScript,has no callback type
"jscallname": "hello", // JavaScript call name
"jscallmode": "sync" // Sync is synchronous execution, and Async is asynchronous execution
},
{
name: "xxx",
....
}
]
}
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 |
The returntype
field has no callback type
When there are multiple levels when returning, it is not recommended to use in the returntype
-
The
array
type received in Golang is a string*C.Char
type, which needs to be use[]interface{}
andjson.Unmarshal
-
The
array
type is when Golang returns*C.Char
type, usejson.Marshal
-
The
array
type is an Array type when JavaScript is passed, but currently only supports one layer when receiving. Please use string method to return multiple layers in Golang, and then use JavaScript'sJSON.parse
When there are multiple levels when returning, it is not recommended to use in the returntype
-
The
object
type received in Golang is a string type. You need to use[string]interface{}
andjson.Unmarshal
-
The
object
type is when Golang returns*C.Char
type, usejson.Marshal
-
The
object
type is an Object type when JavaScript is passed, but currently only supports one layer when receiving. Please use string method to return multiple layers in Golang, and then use JavaScript'sJSON.parse
/goaddon.json
{
"name": "demoaddon",
"sources": [
"demoaddon.go"
],
"output": "./demoaddon/",
"exports": [
{
"name": "Hello",
"args": [
{
"name": "name",
"type": "string"
}
],
"returntype": "string",
"jscallname": "hello",
"jscallmode": "sync"
}
]
}
/demoaddon.go
package main
import "C"
//export Hello
func Hello(_name *C.char) *C.char {
// args is string type,return string type
name := C.GoString(_name)
res := "hello"
ch := make(chan bool)
go func() {
// Time consuming task processing
time.Sleep(time.Duration(2) * time.Second)
if len(name) > 0 {
res += "," + name
}
ch <- true
}()
<-ch
return C.CString(res)
}
/test.js
const demoaddon = require('./demoaddon')
const name = "awen"
const res = demoaddon.hello(name)
console.log('>>> ', res)
/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"
}
]
}
/demoaddon.go
package main
import "C"
//export Hello
func Hello(_name *C.char, cbsFnName *C.char) *C.char {
// args is string type,return string type
name := C.GoString(_name)
res := "hello"
ch := make(chan bool)
go func() {
// Time consuming task processing
time.Sleep(time.Duration(2) * time.Second)
if len(name) > 0 {
res += "," + name
}
ch <- true
}()
<-ch
return C.CString(res)
}
/test.js
const demoaddon = require('./demoaddon')
const name = "awen"
demoaddon.hello(name, funciton(res){
console.log('>>> ', res)
})
MIT