【问题标题】:Calling functions in an so file from Go从 Go 调用 so 文件中的函数
【发布时间】:2015-02-14 21:06:01
【问题描述】:

是否可以从 Go 调用静态对象 (.so) 文件? 我一直在 Google 上搜索,我一直在声称我可以做到

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

但尝试这样做会出错

undefined: syscall.LoadLibrary

并通过 Godocs 搜索,我在 syscall 包中找不到对此函数的引用。 是否可以加载库并调用其函数?

【问题讨论】:

  • syscall.LoadLibrary 是一个windows函数。为什么不直接使用cgo

标签: go static-libraries system-calls


【解决方案1】:

在 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)
}

【讨论】:

  • bar是一个void指针,如何转换成函数指针在Go中调用?
  • 据我所知,唯一的方法是使用 C 函数(您可以使用 cgo 向 Go 公开),它接受指针以及函数的任何参数,将指向适当函数指针类型的指针,然后使用提供的参数调用它。
【解决方案2】:

正如@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

【讨论】:

  • 嗯,我正在努力了解如何使用 CGO。但是您的意思是,没有与Python的(例如)Ctypes模块等效的: cdll.LoadLibrary(...) ?
  • @Caveman 理论上你可以用 CGO 模块包装加载库,但为什么呢?你的用例是什么?我不认为 Go 支持除 CGO 之外的任何类型的动态链接。您为什么要努力了解如何使用 CGO?
  • 不用包含头文件也可以使用这个吗?
【解决方案3】:

@Martin Törnwall 的回答解释了如何使用 dlopen() 进行函数查找。添加此答案以包含有关如何实际调用该函数的示例代码。 (使用 cmets 中建议的方法)。

想法是用 C 语言为共享库中的每个函数编写一个包装函数,它接受一个 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
}

【讨论】:

    猜你喜欢
    • 2020-05-07
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2011-09-01
    • 2019-09-18
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多