本文章,介绍 go 调用 so 里的函数。
生成 so 文件
首先编写 add.c
源代码,里面有个简单的 add
函数,用于加法运算。
#include "stdio.h"
int add(int a,int b) {
printf("a+b=%d\n", a+b);
return a+b;
}
然后生成 so 文件
gcc -fPIC -shared -o add.so add.c
方式 1-通过 cgo 调用
思路是,编写 c 代码调用 so 库,然后 go 再调用 c 代码。
c 调用 so 文件
同一个目录,创建 goLoadSo.c
文件,内容如下,里面加载刚刚生成的 ./add.so
#include <stdio.h>
#include <dlfcn.h>
int main(){
// 手动加载指定位置的so动态库
void* handle = dlopen("./add.so",RTLD_LAZY);
int (*add)(int a,int b);
// 根据动态链接库操作句柄与符号,返回符号对应的地址
add = dlsym(handle,"add");
int sum = add(5,6);
printf("5+6=%d\n", sum);
dlclose(handle);
return sum;
}
然后编译测试一下,生成 goLoadSo
# -ldl 表示调用动态库
gcc -o goLoadSo goLoadSo.c -ldl
执行 goLoadSo
./goLoadSo
# 得到结果
a+b=11
5+6=11
go 调用 c 文件
同一个目录,创建 goLoad.go
文件,内容如下,需要注意的是 import "C"
和上面的注释中间不能有空行。
package main
/*
#cgo LDFLAGS: -ldl
#include "./goloadSo.c"
int LoadSo();
*/
import "C"
import "fmt"
func main () {
fmt.Println(C.LoadSo())
}
然后编译
go build goLoad.go
然后执行
./goLoad
# 输出
a+b=11
5+6=11
11
方式 2-通过第三方包调用
下载包 go get github.com/ebitengine/purego
,这个包可以直接调用 so 文件。
package main
import (
"fmt"
"github.com/ebitengine/purego"
)
func main () {
libc, err := purego.Dlopen("./add.so", purego.RTLD_LAZY|-purego.RTLD_LOCAL)
if err !=nil{
panic(err)
}
defer purego.Dlclose(libc)
// 注册
var add func(int,int)int
purego.RegisterLibFunc(&add,libc,"add")
fmt.Println(add(2,3))
}
执行代码
go run purego.go
# 输出
a+b=5
5