首页 > 解决方案 > 为什么不允许将 interface{} 转换为 cgo 类型?

问题描述

这更像是一个技术问题,而不是真正的问题。由于我们在 cgo 中没有可变参数函数并且目前没有有效的解决方案,我想知道是否可以将 interface{} 转换为 cgo 类型。所以这将使我们有更多的动态功能。我很确定我们甚至不允许以动态方式为导出(//export)函数中的参数分配类型,也不允许使用省略号。那么所有这些限制背后的原因是什么?

谢谢回答。

import "C"

//export Foo
func Foo(arg1, arg2, arg3) {
    
}

标签: gocgo

解决方案


允许但不要求 C 编译器使用不同的返回机制返回不同的类型。例如,一些 C 编译器可能会在寄存器中返回float结果,在寄存器中返回结果,在寄存器中返回整数结果,在寄存器中返回指针结果。%f0double%f0:f1%d0%a0

对于为 Go 编写 Cgo 接口的人来说,这意味着他们通常必须以不同的方式处理这些 C 函数中的每一种。换句话说,不可能这样写:

generic_type Cfunc(ctype1 arg1, ctype2 arg2) { ... }

我们必须知道,在编译时,它Cfunc返回 float/double/<some-integer-type>/<some-pointer-type> 以便我们可以获取正确的寄存器并填充其(或它们的)值) 进入 Cgo 返回值槽,Cgo 接口可以在其中获取并包装它以供 Go 使用。

这对您来说意味着什么,作为实现 Cgo 包装器以调用 C 函数的 Go 编译器的用户,您必须知道正确的类型。没有普遍的答案;这里没有办法使用interface{}。您必须将准确、正确的类型传达给 Cgo 层,以便 Cgo 层可以使用该准确、正确的类型信息在编译时生成正确的机器代码。

如果 C 编译器编写者有某种方式标记他们的代码,例如,在链接时,链接器可以拉入正确的“将正确的寄存器保存到内存”位置,这将使 Cgo 包装器作者能够使用链接器自动在链接时找到 C 函数的类型。但是这些 C 编译器不向链接器提供这种能力。

您的特定编译器是其中之一吗?我们不知道:你没有说。但:

我很确定我们甚至不允许以动态方式为导出(//export)函数中的参数分配类型,也不允许使用省略号。那么所有这些限制背后的原因是什么?

这是正确的,上面的(略带理论性的)示例是一个原因。(我通过混合来自 68k C 编译器和 SPARC C 编译器的实际技术构建了这个示例,所以我认为没有像这样的单个 C 编译器。但是这样的示例在过去确实存在,并且 SPARC 系统仍然以 % 为单位返回整数V8 SPARC 上的 o0 或 %o0+%o1,而 %f0 或 %f0+%f1 中的浮点数。)


推荐阅读