为什么来自不同模块的 Go C 类型会不同?

Joh*_*s P 3 go cgo

在 Go 中,由于类型不兼容,我遇到了编译错误,我无法解释。我正在使用该"C"模块。最小示例包含以下 2 个文件:

package module

import "C"

type T struct {
    X C.int
}
Run Code Online (Sandbox Code Playgroud)

和一个主程序

package main

import (
    "fmt"
    "sandbox/module"
)

import "C"

func f() *module.T {
    var x C.int = 42
    return &module.T{X: x}
}

func main() {
    fmt.Printf("value: %d", f().X)
}
Run Code Online (Sandbox Code Playgroud)

这无法编译并显示消息 ./main.go:12: cannot use x (type C.int) as type module.C.int in field value

由于某种原因,编译器认为C.int不等于module.C.int

它一定与模块有关,C并且代码分布在两个模块中,因为如果我从C.intplain切换到它,它会突然起作用int

为什么这段代码不能编译?使其编译而不将所有代码压缩在一个模块中的正确解决方案是什么?

我在 Ubuntu 16.04 上使用最新的 Go 编译器 1.9.2。

pet*_*rSO 6

命令cgo

转到 C 的参考文献

Cgo 将 C 类型转换为等效的未导出的 Go 类型。由于翻译未导出,因此 Go 包不应在其导出的 API 中公开 C 类型:一个 Go 包中使用的 C 类型与另一个 Go 包中使用的相同 C 类型不同。

你说,“出于某种原因,编译器认为 C.int 不等于 module.C.int。” 正如 cgo 命令文档所解释的,不同包中未导出的 Go 类型并不相同。

不要在导出的 API 中公开 C 类型。例如,

module.go:

package module

type T struct {
    X int
}
Run Code Online (Sandbox Code Playgroud)

main.go:

package main

import (
    "fmt"
    "sandbox/module"
)

import "C"

func f() *module.T {
    var x C.int = 42
    return &module.T{X: int(x)}
}

func main() {
    fmt.Printf("value: %d\n", f().X)
}
Run Code Online (Sandbox Code Playgroud)

输出:

value: 42
Run Code Online (Sandbox Code Playgroud)