测试动态库
test_so.h
int test_so_func(int a,int b);
test_so.c
#include "test_so.h"
int test_so_func(int a,int b)
{
return a*b;
}
生成so
gcc -shared ./test_so.c -o test_so.so
复制so文件到Go项目目录
Go项目目录
load_so.h
int do_test_so_func(int a,int b);
load_so.c
#include "load_so.h"
#include <dlfcn.h>
int do_test_so_func(int a,int b)
{
void* handle;
typedef int (*FPTR)(int,int);
handle = dlopen("./test_so.so", 1);
FPTR fptr = (FPTR)dlsym(handle, "test_so_func");
int result = (*fptr)(a,b);
return result;
}
test.go
package main
/*
#include "load_so.h"
#cgo LDFLAGS: -ldl
*/
import "C"
import "fmt"
func main() {
fmt.Println("20*30=", C.do_test_so_func(20, 30))
}
Go项目目录要放在$GOPATH/src/
目录下,这也是正常操作。
├── bin
├── pkg
└── src
└── test
├── go.mod
├── load_so.c
├── load_so.h
├── test
├── test.go
├── test_so.c
├── test_so.h
└── test_so.so
test目录为Go项目,里边是上述创建的所有源码文件。
在$GOPATH/src/test/
里直接使用go build
编译生成test
二进制文件,此处需要注意执行路径。
运行
$ ./test
20*30= 600
问题
1、/* */注释的代码下一行一定是import “C”,中间不能有空行
2、import "C"必须单独一行,不能和其它库一起导入
3、有人编译的时候会报错:
$ go build
# command-line-arguments
/tmp/go-build489385520/b001/_x002.o: In function `_cgo_49a6b71449ae_Cfunc_do_test_so_func':
/tmp/go-build/cgo-gcc-prolog:54: undefined reference to `do_test_so_func'
collect2: error: ld returned 1 exit status
这个主要是执行目录问题,一定要在$GOPATH/src/项目/
目录下,用go build
执行,go build
后边不要有任何文件名。
或者用go run .
运行,或者go run test
,test是项目名。不能用go run test.go
。
4、还有人报这个错:
$ go build
# test
/tmp/go-build043875804/b001/_x003.o: In function `do_test_so_func':
./load_so.c:17: undefined reference to `dlopen'
./load_so.c:18: undefined reference to `dlsym'
collect2: error: ld returned 1 exit status
test.go文件里的cgo LDFLAGS: -ldl
这一行不要删掉。