从Go调用so文件中的函数

从Go调用so文件中的函数,go,static-libraries,system-calls,Go,Static Libraries,System Calls,是否可以从Go调用静态对象(.so)文件? 我一直在谷歌上搜索,我一直在寻找我能做的事情 lib, _ := syscall.LoadLibrary("...") 但尝试这样做会产生错误 undefined: syscall.LoadLibrary 在Godocs中搜索时,我在syscall包中找不到该函数的引用。 是否可以加载一个库并调用它的函数?正如@JimB所说,您应该使用CGO,并将指向动态/静态库的链接放在那里。根据这个例子: // #cgo LDFLAGS: -lpng // #

是否可以从Go调用静态对象(.so)文件? 我一直在谷歌上搜索,我一直在寻找我能做的事情

lib, _ := syscall.LoadLibrary("...")
但尝试这样做会产生错误

undefined: syscall.LoadLibrary
在Godocs中搜索时,我在syscall包中找不到该函数的引用。
是否可以加载一个库并调用它的函数?

正如@JimB所说,您应该使用CGO,并将指向动态/静态库的链接放在那里。根据这个例子:

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

...

var x:= C.png_whatever() // whatever the API is
/#cgo LDFLAGS:-lpng
//#包括
输入“C”
...
var x:=C.png_whatever()//不管API是什么

在这里阅读更多信息:

在POSIX平台上,您可以使用
cgo
拨打电话和联系朋友:

// #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)
}
/#cgo LDFLAGS:-ldl
//#包括
输入“C”
进口fmt
func foo(){
句柄:=C.dlopen(C.CString(“libfoo.so”),C.RTLD_-LAZY)
杆:=C.dlsym(手柄,C.CString(“杆”))
fmt.Printf(“条形图位于%p\n”,条形图)
}

由@Martin Törnwall提供的答案解释了如何使用
dlopen()
进行函数查找。添加此答案以包括如何实际调用该函数的示例代码。(采用评论中建议的方法)

其思想是用C语言为共享库中的每个函数编写一个包装函数,它接受一个void*指针(指向
dlopen()
返回的函数的指针),将其转换为适当的函数指针,然后调用它

假设我们在
libfoo中有一个名为
stru 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
}
主程序包
进口(
“fmt”
)
/*
#cgo LDFLAGS:-ldl
#包括
typedef int(*str_length_type)(char*);//函数指针类型
int str_length(void*f,char*s){//包装函数
返回((str_长度类型)f)(s);
}
*/
输入“C”
func main(){
句柄:=C.dlopen(C.CString(“libfoo.so”),C.RTLD_-LAZY)
str_length_ptr:=C.dlsym(手柄,C.CString(“str_length”))
结果:=C.str_长度(str_长度ptr,C.CString(“你好,世界!”)
fmt.Println(结果)//打印12
}

syscall.LoadLibrary
是一个windows函数。为什么不直接使用cgo呢?嗯,我正努力想知道如何使用cgo。但是你的意思是,没有与Python(例如)的Ctypes模块等价的东西:cdll.LoadLibrary(…)?@Caveman理论上你可以用CGO模块包装加载库,但是为什么呢?你的用例是什么?我认为Go除了CGO之外不支持任何类型的动态链接。为什么你在苦苦思考如何使用CGO?是否可以在不包含头文件的情况下使用它?条形图是一个空指针,如何将其转换为函数指针并在Go中调用它?据我所知,唯一的方法是使用C函数(可以使用
CGO
公开Go)它接受指针以及函数的任何参数,将指针强制转换为适当的函数指针类型,然后使用提供的参数调用它。