Golang中为什么没有针对dylib的LoadLibrary函数

Golang中为什么没有针对dylib的LoadLibrary函数 Go 语言在 /x/sys/windows 包中提供了 LoadSystemLibrary 函数,该函数最终会调用 syscall 包中的函数。这使得程序员能够从 Go 代码中动态调用 Windows 机器上 DLL 文件中的函数。然而,尽管 macOS 也包含以 .dylib 为后缀的动态库,却没有加载这些文件的等效函数。

为什么不存在这样的函数呢?是因为没有人花时间去编写它,还是根本不可能实现?如果可能实现,是否有任何(任何语言的)实现可供我参考,以便编写 Go 版本?

我做了很多研究,发现了这个页面,它解释了如何读取 Mach-O 文件(dylib 的另一种名称)。有没有办法在加载这些函数后调用它们呢?我还考虑过或许可以创建一个虚拟机来解释这些文件。

编辑: 我刚刚发现了这个 godoc,它可以打开和读取 Mach-O 文件。但这仍然没有解释如何实际调用函数,而这正是我的主要目的。


更多关于Golang中为什么没有针对dylib的LoadLibrary函数的实战教程也可以访问 https://www.itying.com/category-94-b0.html

2 回复

请参考 https://github.com/golang/go/issues/18296。这里有一个使其生效的概念验证:https://github.com/notti/nocgo/

更多关于Golang中为什么没有针对dylib的LoadLibrary函数的实战系列教程也可以访问 https://www.itying.com/category-94-b0.html


Go语言在标准库中确实没有提供直接加载和调用macOS dylib的函数,这主要是因为平台差异和Go的设计哲学。不过,通过cgo和系统调用,可以实现类似的功能。以下是一个示例,展示如何通过cgo动态加载和调用dylib中的函数:

package main

/*
#cgo LDFLAGS: -ldl
#include <dlfcn.h>
#include <stdlib.h>
*/
import "C"
import (
    "fmt"
    "unsafe"
)

func main() {
    // 加载dylib
    libPath := C.CString("/usr/lib/libSystem.B.dylib")
    defer C.free(unsafe.Pointer(libPath))
    
    handle := C.dlopen(libPath, C.RTLD_LAZY)
    if handle == nil {
        panic("failed to load library")
    }
    defer C.dlclose(handle)
    
    // 获取函数指针
    funcName := C.CString("printf")
    defer C.free(unsafe.Pointer(funcName))
    
    funcPtr := C.dlsym(handle, funcName)
    if funcPtr == nil {
        panic("failed to find function")
    }
    
    // 将函数指针转换为Go可调用形式
    printf := (*func(string) int)(unsafe.Pointer(&funcPtr))
    
    // 调用函数
    result := (*printf)("Hello from dylib!\n")
    fmt.Printf("Printed %d characters\n", result)
}

需要注意的是,这种方法需要cgo,并且函数签名必须手动匹配。对于复杂的函数调用,可能需要更精细的类型转换和内存管理。此外,Go团队可能没有在标准库中直接提供这样的函数,是因为跨平台动态库加载的复杂性较高,且与Go的静态链接哲学不完全一致。社区中也有一些第三方库尝试提供跨平台的动态加载支持,但标准库目前主要聚焦于Windows的DLL加载。

回到顶部