背景
在开发electron项目中,很多依赖node 的方式效率比较低,为了提高效率需要Node C++ addon 插件 但是不会c++ 会点golang 于是自己尝试写个demo
技术方案
node 提供node-ffi调用动态链接库,因此golang程序需要最终编译成动态链接库
- mac 环境下是.dylib文件
- win环境是.dll文件
- linux 环境下是.so文件
golang demo
直接上代码
// bridge.gopackage main// typedef void (*cb)(char* extra, char* data);// void callCb(cb callback, char* extra , char* arg) { // c的回调, go将通过这个函数回调c代码// callback(extra,arg);// }import "C"
// gofun.gopackage main/*#cgo CFLAGS: -I .#include <unistd.h>#include <stdio.h>#include <string.h>#include <stdlib.h>typedef void (*cb)(char* extra, char* data);extern void callCb(cb callback, char* extra, char* arg);*/import "C" // C是一个虚包, 上面的注释是c代码, 可以在golang中加 `C.` 前缀访问, 具体参考上面给出的文档import "time"//export hellofunc hello(arg *C.char) *C.char { //name := gjson.Get(arg, "name") //return "hello" + name.String() return C.CString("hello peter:::" + C.GoString(arg))} // 通过export注解,把这个函数暴露到动态链接库里面//export helloPfunc helloP(arg *C.char, ccb C.cb, extra *C.char) *C.char { C.callCb(ccb, extra, C.CString("one")) time.Sleep(time.Second) C.callCb(ccb, extra, C.CString("two")) return C.CString("hello peter:::" + C.GoString(arg))}func main() { println("go main func")}
编译成动态链接库
我的操作系统是mac
go build -o main.dylib -buildmode=c-shared main.go bridge.go
生成 main.dylib 文件
node部分
var ffi = require('ffi-napi');// 指定路径注册函数var libm = ffi.Library('main', {'helloP': [ 'string', [ 'string' ,ffi.Function("void",['string','string']),'string'] ]});console.log(libm.helloP("1111",function (a,b){console.log(a,b)},"222"))
到此demo 中能完整的演示 go语言生成动态链接库为node 提供扩展
总结:
go语言取代了c++作为node 扩展的可能性,使得node 的性能有了一定的提升,也降低了开发难度,go语言的上手难度比c++低很多。
不足之处:
1.数据类型转换问题,由于对c不了解 js和go直接的数据类型转换成了一个坑
简易处理方案转换成json字符串调用的时候来解析成对象
2.复杂业务还是无法取代c++,比如带界面的扩展,截图一类的工具开发还是得qt做