搜索文档搜索当前语言
互操作
候选版本v0.20260809.0-rc.5

本文档对应当前协同发布候选版本。

互操作

从 C 调用 Go

将 C 声明绑定到 Go 符号,并描述 Go 多返回值。

c2go_linkname 把一个 C 声明绑定到具名 Go 符号。C 签名就是编译器对该 Go 函数 ABI 的描述,因此必须精确匹配。

绑定普通 Go 函数

假设 package example.com/mathx 中包含:

package mathx

func Double(value int) int { return value * 2 }

在 C 中声明并调用:

#include <c2go.h>

extern __c2go_intptr go_double(__c2go_intptr)
    c2go_linkname("example.com/mathx.Double");

c2go_extern __c2go_intptr answer(void) {
    return go_double(21);
}

对普通 Go 函数不要写可选 ABI selector。C2Go 会创建 alias 与 wrapper,桥接到 Go internal ABI。

同包符号

C 声明始终书写完整 Go symbol name;Clang 再用 -fc2go-package 判断它是否属于正在生成的 package。例如使用 -fc2go-package=example.com/mathx 编译上面的声明时,example.com/mathx.Double 会在 LLVM 与 Plan 9 汇编中解析为当前 package 的本地符号,而不是一次跨 package 引用。完整 linkname 仍保留在 IR/manifest 元数据中,供审计和生成流程核对。

不要再把 import path 传给 c2go-bind。Binder 从 manifest 读取它;只有 Go 源码中的 package 名与路径末段不同时,才需要可选的 --pkgname 覆盖。

绑定已有 ABI0 符号

只有目标已经暴露 Go ABI0 入口时才使用 C2GO_GOABI0:

extern void *runtime_alloc(const void *, __SIZE_TYPE__)
    c2go_linkname("github.com/c2gohq/c2go_libc.GCMalloc", C2GO_GOABI0);

这个 selector 表示直接引用,而不是生成 internal-ABI bridge;它不是通用的性能开关。<c2go.h> 已经把这个 runtime 入口公开为 gc_malloc;上面的 alias 只用于说明 ABI selector,不应替代公开 API。

接收多个 Go 返回值

用一个 C struct 字段对应一个 Go result slot:

func DivMod(a, b int32) (int32, int32) {
    return a / b, a % b
}
struct DivMod {
    int quotient;
    int remainder;
};

extern struct DivMod go_divmod(int, int)
    c2go_linkname("example.com/mathx.DivMod")
    c2go_returntype(struct DivMod);

每个字段会降低为独立 Go ABI result slot,不会传递隐藏的 sret 指针。每个字段都必须适合一个受支持 slot:标量、指针、浮点值或受支持的 C2Go aggregate。

函数与变量

c2go_linkname 同时适用于函数与变量。无论哪一种,C 声明中的完整 Go symbol name 与 -fc2go-package 都是构建契约。如果重构 Go package 或符号但没有同步更新它们,最终会链接失败。

当前边界

如果目标是 C ABI 动态库而不是 Go 符号,请使用原生库导入。