为什么不允许将 interface{} 转换为 cgo 类型?

Why casting interface{} to cgo types is not allowed?

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

感谢您的回答。

import "C"

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

允许但不要求 C 编译器使用不同的 return 机制 return 不同的类型。例如,某些 C 编译器可能 return float 导致 %f0 寄存器,double 导致 %f0:f1 寄存器 pair,整数结果在 %d0 寄存器中,指针结果在 %a0 寄存器中。

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

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

我们必须知道,在编译时,Cfunc returns float/double//< some-pointer-type> 这样我们就可以获取 正确的寄存器 并将其(或它们的)值填充到 Cgo return-value 槽中, Cgo 接口可以在哪里获取它并将其包装起来以便在 Go 中使用。

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

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

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

I'm pretty sure we're not even allowed to assign types in a dynamic way to arguments in exported (//export) functions, neither the use of ellipsis is allowed. So what's the reason behind all those limits?

说的对,上面的(略偏理论的)例子就是a原因。 (我通过混合 68k C 编译器和 SPARC C 编译器的实际技术构建了这个例子,所以我不认为有任何一个像这样的 C 编译器。但是这样的例子在过去确实存在,而且 SPARC 系统仍然 return %o0 中的整数,或 V8 SPARC 上的 %o0+%o1,对比 %f0 或 %f0+%f1 中的浮点数。)