GO
-
安装 Gcc tdm-gcc (jmeubank.github.io)
win64位下载地址:https://github.com/jmeubank/tdm-gcc/releases/download/v10.3.0-tdm64-2/tdm64-gcc-10.3.0-2.exe
-
步骤
- 设置编译环境为64位 GOARCH=amd64 ,如果想设置为32位 GOARCH=386
- 需要生成动态库的文件必须要符合以下条件
a. import "C"
b. main函数
c.导出的函数首字母必须大写
d.函数前必须要放//export (函数名)- 生成 dll 或者 os 文件
import "C"
: 如果在Go代码中出现了import "C"语句则表示使用了CGO特性,紧跟在这行语句前面的注释是一种特殊语法,里面包含的是正常的C语言代码。
-
编写 dll
package main
/*
#include
*/
import "C"
import "unsafe"
func main() {
}
var result *C.char
//export Create
func Create(p *C.char) *C.char {
v := C.GoString(p)
result = C.CString(v)
return result
}
//export Free
func Free() {
C.free(unsafe.Pointer(result))
}
Create
:方法体,其中参数为 *C.char
类型,接收NodeJs传递过来的 string 类型参数,返回也是 *C.char
类型,返回为 string 类型返回值。
其中
C.GoString()
(转换C字符串为go字符串),
C.CString()
(转换go的字符串为C字符串,C中的字符串是使用malloc分配的,所以需要调用C.free来释放内存)
✨这里有一点要说明下,Create
返回类型为 *C.char
,nodejs 那边才能拿到对应字符串类型数据,但是因为需要 通过 C.CString()
转换成C对应的字符串才能返回,但是使用了 C.CString()
就需要面临 C.free
释放内存,我通过 defer C.free(unsafe.Pointer())
去释放,释放后返回值就出现了问题,但是不释放我测试了下 10W 次调用 Create
方法,内存就一直递增,没办法我只有写一个专用的方法来释放内存...
Free
: 方法体,释放 C.CString()
分配的内存,原因上面说明,我不晓得有啥其他解决方法,懂C 和 Go 的大大们,有啥解决方法帮我留个言,我确实不晓得咋个搞了....
C.free()
是存在 stdlib.h
库中的,所以需要在 import "C"
上注释增加:
/*
#include
*/
注释与 import "C"
之间不能有换行、空格。
Go中写C代码,可以了解下 CGO入门了解传送门
-
编译 动态库
// test.dll 是windows 动态库
go build -o test.dll -buildmode=c-shared main.go
// test.so 是mac 动态库
go build -o test.so -buildmode=c-shared main.go
NodeJs
-
准备工作
-
安装 cnpm 淘宝 NPM 镜像 (npmmirror.com)
npm install -g cnpm --registry=https://registry.npmmirror.com
-
安装 Python 2.7 Python 2.7.0 Release | Python.org
win64位下载地址:https://www.python.org/ftp/python/2.7/python-2.7.amd64.msi
-
全局安装 windows-build-tools 工具包
cnpm install --global --production windows-build-tools
-
安装 windows-build-tools 卡住时可参考 安装 windows-build-tools 卡在 Python 2.7 - (jianshu.com)
-
安装 node-ffi-napi
cnpm install ffi-napi
-
使用方式
const ffi = require("ffi-napi")
const path = require("path")
const Dll = ffi.Library(path.resolve("dll/t.dll"), {
Create: ["string", ["string"]],
Free: ["void", []]
})
Dll.Create("哈哈哈哈!!!!!!!!!!")
Dll.Free();
使用 ffi.Library
加载 dll 文件,其中 Create
、Free
为 dll 暴露的方法名,[]
中第一个参数为返回值类型, 第二个参数也是 []
数组,为方法体的参数类型,多个以逗号分隔。
然后直接通过 Dll 调用对应声明的方法体就行了!!! Over!!!