zl程序教程

您现在的位置是:首页 >  工具

当前栏目

golang动态库调用方式

Golang 方式 动态 调用
2023-09-27 14:22:01 时间

golang 调用动态库在使用第三方功能比较常见。
方法如下:

  1. 编写c语言代码实现动态库的调用,然后cgo引用c代码,间接方式实现动态库的调用。
    优点:
    通用性强,没什么难度。
    缺点:
    多了一次封装代码可能比较繁琐

  2. 使用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"))
}