本文章,介绍 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
最后修改:2023 年 12 月 30 日
如果觉得我的文章对你有用,请随意赞赏