GO
-
步骤
- 设置编译环境为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 <stdlib.h>
*/
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 <stdlib.h>
*/
注释与 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
npm 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!!!









网友评论