Golang调用so文件示例

测试动态库

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这一行不要删掉。

发布了162 篇原创文章 · 获赞 131 · 访问量 83万+

猜你喜欢

转载自blog.csdn.net/u013474436/article/details/105246605