Golang編寫動態庫實現回調函數
我們現在要做一個動態庫,但是C++實在是比較難,於是就想能不能用更簡單的golang來實現,golang也就是最近的版本才支持編譯成動態庫,在網上也沒找到可用的案例,好在我們解決了這個問題,這邊寫個筆記造福大眾。
main.go
package main
/*
#cgo CFLAGS: -I .
#include <unistd.h>
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
typedef void (*callback)(void *,int);
extern void c_callback (void *,int);
extern callback _cb;
*/
import "C"
import (
"encoding/json"
"unsafe"
)
func funccallback(gostring string,goint int) {
var cmsg *C.char = C.CString(gostring)
var ivalue C.int = C.int(len(gostring))
defer C.free(unsafe.Pointer(cmsg))
C.c_callback(unsafe.Pointer(cmsg),ivalue)
}
//export register_rsucallback
func register_rsucallback(p C.callback) {
C._cb = p;
return
}
//export test_callback
func test_callback() {
funccallback("hello,this is func callback.",123)
}
func main() {
}
bridge.go
package main
/*
#include <stdio.h>
typedef void (*callback)(void *,int);
callback _cb;
void c_callback(void* p,int i)
{
_cb(p,i);
}
*/
import "C"
這樣寫完直接調用以下命令即可生成main.dll文件和main.h文件
go build -o main.dll -buildmode=c-shared main.go bridge.go
然后就是C語言的測試程序調用
main.c
#include <stdio.h>
#include "main.h"
void gocallback(void* s,int len) {
printf("raw data: %s\n",s);
}
int main() {
// 注冊回調
register_callback(gocallback);
// 測試回調
test_callback();
}
把C程序編譯一下即可測試。
有時我們需要在別的包里調用這個回調函數,這時可以做一個工具
utils包callbackutils.go
package utils
type funVarType func(string,int)
var FunVar func(string,int)
func SetFuncAddr(a funVarType) {
FunVar=a
}
func Funccallbackutil (gostring string,i int) {
FunVar(gostring,i)
}
在main.go中可以寫個init函數做個初始化
func init() {
utils.SetFuncAddr(funccallback)
}
然后在寫一個測試的函數導出
//export test_callbackutil
func test_callbackutil() {
utils.Funccallbackutil("hello this is func callbackutil test",123)
}
最后在main.c中調用測試函數即可測試。