golang调用so动态库调用方式 linux
golang 调用动态库在使用第三方功能比较常见。
方法如下:
-
编写c语言代码实现动态库的调用,然后cgo引用c代码,间接方式实现动态库的调用。
优点:
通用性强,没什么难度。
缺点:
多了一次封装代码可能比较繁琐 -
使用syscall包进行调用,适用与linux,windows.比较广泛。推荐使用。
优点:
没有cgo代码,syscall底层直接使用汇编语言实现,比较彻底。无依赖。
缺点:
不支持linux / macos
注意事项:
syscall不同平台,函数定义是不一样的,属于平台相关代码,查看文档时注意区分。
途径
下面这些项目只是测试,并不能真正应用生产项目
purego【推荐,稳定可用】
https://kgithub.com/ebitengine/purego
示例
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!")
}
https://github.com/notti/nocgo
实验性质,生产环境不推荐
// Load the library
lib, err := nocgo.Open("libpcap.so")
if err != nil {
log.Fatalln("Couldn't load libpcap: ", err)
}
// func specification
var pcapOpenLive func(device []byte, snaplen int32, promisc int32, toMS int32, errbuf []byte) uintptr
// Get a handle for the function
if err := lib.Func("pcap_open_live", &pcapOpenLive); err != nil {
log.Fatalln("Couldn't get pcap_open_live: ", err)
}
// Do the function call
errbuf := make([]byte, 512)
pcapHandle := pcapOpenLive(nocgo.MakeCString("lo"), 1500, 1, 100, errbuf)
// Check return value
if pcapHandle == 0 {
log.Fatalf("Couldn't open %s: %s\n", "lo", nocgo.MakeGoStringFromSlice(errbuf))
}
// pcapHandle can now be used as argument to the other libpcap functions
dl
https://github.com/rainycape/dl 【不推荐】
年久失修
package main
import "C"
import (
"log"
"github.com/rainycape/dl"
)
func main() {
lib, err := dl.Open("../lib/server/server.so", 0)
if err != nil {
log.Fatalln(err)
}
defer lib.Close()
// printC
var printC func(d *C.char)
lib.Sym("PrintTestC", &printC)
printC(C.CString("Prin Example SO funtion"))
}