从Go调用so文件中的函数

w8rqjzmb  于 2023-03-27  发布在  Go
关注(0)|答案(4)|浏览(342)

可以从Go语言中调用静态对象(.so)文件吗?我一直在Google上搜索,我一直在寻找我可以做的声明

lib, _ := syscall.LoadLibrary("...")

但尝试这样做会产生错误

undefined: syscall.LoadLibrary

我在Godocs中找不到这个函数的引用。可以加载一个库并调用它的函数吗?

wkyowqbh

wkyowqbh1#

在POSIX平台上,可以使用cgo调用dlopen和朋友:

// #cgo LDFLAGS: -ldl
// #include <dlfcn.h>
import "C"

import fmt

func foo() {
     handle := C.dlopen(C.CString("libfoo.so"), C.RTLD_LAZY)
     bar := C.dlsym(handle, C.CString("bar"))
     fmt.Printf("bar is at %p\n", bar)
}
9lowa7mx

9lowa7mx2#

正如@JimB所说,你应该使用CGO,并将链接放在动态/静态库中。按照这个例子:

// #cgo LDFLAGS: -lpng
// #include <png.h>
import "C"

...

var x:= C.png_whatever() // whatever the API is

在此阅读更多信息:http://blog.golang.org/c-go-cgo

qkf9rpyu

qkf9rpyu3#

@Martin Törnwall的答案解释了如何使用dlopen()进行函数查找。添加此答案以包括如何实际调用该函数的示例代码。(使用注解中建议的方法)。
这个想法是用C语言为共享库中的每个函数编写一个 Package 器函数,它接受一个void* 指针(指向dlopen()返回的函数的指针),将其转换为适当的函数指针,然后调用它。
假设我们在libfoo.so中有一个名为str_length的函数来计算字符串的长度,那么得到的Go代码将是:

package main

import (
    "fmt"
)

/*
#cgo LDFLAGS: -ldl
#include <dlfcn.h>

typedef int (*str_length_type)(char*); // function pointer type

int str_length(void* f, char* s) { // wrapper function
    return ((str_length_type) f)(s);
}
*/
import "C"

func main() {
    handle := C.dlopen(C.CString("libfoo.so"), C.RTLD_LAZY)
    str_length_ptr := C.dlsym(handle, C.CString("str_length"))
    result := C.str_length(str_length_ptr, C.CString("Hello World!"))
    fmt.Println(result) // prints 12
}
fv2wmkja

fv2wmkja4#

发现使用purego更容易,他们的README示例工作:

package main

import (
    "fmt"
    "runtime"

    "github.com/ebitengine/purego"
)

func getSystemLibrary() string {
    switch runtime.GOOS {
    case "darwin":
        return "/usr/lib/libSystem.B.dylib"
    case "linux":
        return "libc.so.6"
    default:
        panic(fmt.Errorf("GOOS=%s is not supported", runtime.GOOS))
    }
}

func main() {
    libc, err := purego.Dlopen(getSystemLibrary(), purego.RTLD_NOW|purego.RTLD_GLOBAL)
    if err != nil {
        panic(err)
    }
    var puts func(string)
    purego.RegisterLibFunc(&puts, libc, "puts")
    puts("Calling C from Go without Cgo!")
}

相关问题