把 C 编译成无需 cgo 的 Go package。

使用 C2Go 将 C 源码提前编译成可导入的 Go package,让代码在 Go runtime 中运行,并支持无需 cgo 的消费者构建。

  • PureGo · CGO_ENABLED=0
  • Go GC 感知
  • C ABI 互操作
C source
→
c2go-clang
→
Plan 9 + JSON
→
c2go-bind
→
Go package
c2go-libc提供 C runtime 与 Go runtime 的兼容层
C 输入
#include <c2go.h>

c2go_extern int add(int a, int b) {
  return a + b;
}
→
Go 调用
import "example.com/demo/translated"

result := translated.Add(20, 22)

C2Go

C-to-Go 编译工具链,而不是源码改写器

C2Go 是一种基于 Clang 的提前编译模式,适合把现有 C 实现复用或迁移到普通 Go package 中。它生成供 Go assembler 使用的 Plan 9 汇编与结构化 manifest,再由 c2go-bind 生成 Go 工具链可以直接构建的 package。

它不会承诺把任意 C 自动改写成人工维护的 Go 源码。C2Go 保留 C 作为实现语言,同时让产物使用 goroutine 栈、Go 调度器和可选的 GC 感知内存模型。

无需 cgo 的 Go 构建

生成产物不依赖 import "C"。c2go-libc 使用 PureGo 原生调用桥,让消费者可以在 CGO_ENABLED=0、没有宿主 C 编译器的环境构建。

开始使用
terminal
CGO_ENABLED=0 go build ./...

# No import "C"
# No host C compiler required
managed.c
struct managed Node { struct Node *next; };

struct Node *node = gc_malloc(
  c2go_typeinfo(struct Node), sizeof(*node));
node->next = gc_malloc(
  c2go_typeinfo(struct Node), sizeof(*node->next));

// Both objects are tracked by the Go GC.

Go GC 感知的内存分配

显式 managed record 可以通过 c2go-libc 在 Go heap 分配。类型信息描述指针布局,让 GC 精确扫描对象。

开始使用
C sourceanswer = go_answer(21);
call →
Go symbolfunc Answer(v int32) int32

从 C 调用 Go

用 c2go_linkname 声明 Go 符号,让 C 代码直接调用 Go 函数,并由编译器保持 ABI 边界一致。

开始使用
native.c
extern double vendor_scale(double);

double scaled_value(double value) {
  return vendor_scale(value);
}

调用原生库

只有声明、没有定义的函数会自动导入系统或第三方 C ABI;链接参数由 c2go-bind 记录并带入最终 Go package。

开始使用
native APIregister_cb(callback);
← callback
C2Go functionc2go_callback(on_value)

跨越边界的回调

将 C2Go 编译的函数包装成原生函数指针,或显式导入宿主地址,用于真实 C 回调接口。

开始使用

几分钟完成 C → Go

1

安装

下载与当前宿主平台匹配的 SDK,并固定配套的 c2go-libc 版本。

export C2GO_HOME=/path/to/c2go-sdk
export PATH="$C2GO_HOME/bin:$PATH"
go get github.com/c2gohq/c2go_libc@v0.20260809.0-rc.5
2

编译

c2go-clang 生成 Plan 9 汇编和 JSON manifest。

mkdir -p .c2go
c2go-clang --target="$C2GO_TARGET" \
  -fc2go -fc2go-package=example.com/demo/translated \
  -fc2go-emit-plan9-asm=.c2go/translated.s \
  -fc2go-emit-manifest=.c2go/translated.json \
  .c2go/input.c
3

绑定

c2go-bind 将产物组装成普通 Go package。

mkdir -p translated
c2go-bind --out=translated --sidecar=.c2go/translated.json \
  .c2go/translated.s
go test ./...

当前 SDK 平台

Linuxamd64
Linuxarm64
Windowsamd64
macOSarm64

i候选版本;二进制尚未签名,API 和 ABI 仍可能调整。

C2Go 常见问题

C2Go 会把 C 改写成 Go 源码吗?

不会做通用的 source-to-source 改写。c2go-clang 编译 C,c2go-bind 再生成组成普通 Go package 所需的 .go 与 .s 文件。

最终 Go package 需要 cgo 吗?

不需要。生成阶段需要 C2Go SDK,但消费者可以在 CGO_ENABLED=0、没有宿主 C 编译器的环境中构建。

目前支持哪些代码和平台?

当前候选版本面向 C,不支持 C++;发布页提供 Linux amd64/arm64、Windows amd64 与 macOS arm64 SDK。采用前应核对语言、ABI、回调和栈指针限制。

现在适合直接用于生产吗?

当前发布仍是 pre-1.0 候选版本,二进制尚未签名,API 与 ABI 也可能变化。它更适合评估、兼容性验证和受控迁移。

从 Hello World 开始

从一个 C 加法函数开始,逐步理解 Go GC 管理的内存、互操作和多文件构建。

开始使用