当我通过 Cgo 导入使用 C 包的 2 个不同包时,Go 编译返回架构 x86_64 错误的重复符号

vut*_*ran 6 c linker go cgo blockchain

这是我的代码:

package main

import (
    kusb "github.com/karalabe/usb"
    tusb "github.com/trezor/trezord-go/usb"
)

func main() {
    kusb.Enumerate(0, 0)
    tusb.InitHIDAPI(nil)
}
Run Code Online (Sandbox Code Playgroud)

当我编译时(我用来go mod管理包),它返回以下错误:

duplicate symbol _libusb_dev_mem_alloc in:
    /var/folders/fm/1rln65d94mn45s0h5l78tdyh0000gp/T/go-link-624554542/000002.o
    /var/folders/fm/1rln65d94mn45s0h5l78tdyh0000gp/T/go-link-624554542/000020.o
ld: 136 duplicate symbols for architecture x86_64
clang: error: linker command failed with exit code 1 (use -v to see invocation)
Run Code Online (Sandbox Code Playgroud)

为什么?

我进行了一些调查:

  1. 这两个包都使用相同的hidapiClibusb包来与 USB 设备交互。
  2. 这些 C 包是相同的,因此它定义了相同的函数,所以我认为它与错误直接相关。
  3. 在 中trezord-go/usb,它们包含.C文件,而不是头文件。

这对我来说非常违反直觉,因为从包用户的角度来看,我不需要担心 C 包在包内部如何使用,只需要担心公开的类型、函数及其行为。

谁能真正解释一下这里发生了什么以及我如何导入它们?尽管它们使用相同的 C 包,但它们执行不同的功能。

小智 1

从这里: https: //www.repustate.com/blog/go-duplicate-symbols-for-architecture-x86_64/

“这是什么意思?嗯,这意味着我们正在尝试从两个(或更多)不同的源文件链接相同的符号名称(在我们的例子中是一个方法)。解决方法很简单:通过更新来重命名其中一个方法头文件、源文件(.c 或 .cpp 文件),最后更新对 Go 代码中符号的引用(如果在那里直接引用的话)。

有帮助吗?