搜索文档搜索当前语言
开始使用
候选版本v0.20260809.0-rc.5

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

开始使用

项目概览

理解 C2Go 会生成什么、代码在哪里运行,以及它适合解决哪些问题。

C2Go 是 Clang 的一种编译模式,它会把 C 源码编译成可由 Go 工具链构建的 Go package 产物。生成的代码运行在 Go runtime 下:使用 goroutine 栈和调度器,可以分配 Go GC 可见的对象,也可以跨越 C/Go 边界调用函数。

这是提前编译,不会把 C 编译器嵌入应用,也不会在程序启动时临时编译 C。

工具链会生成什么

对于一组 C 源文件,c2go-clang 会生成:

  • 交给 Go assembler 的 Plan 9 汇编(.s);
  • 描述导出符号、类型、目标平台、回调和链接参数的 JSON manifest。

c2go-bind 读取汇编与 manifest,把生成的 .go、.s 文件写入普通 Go package,最后由 go build 或 go test 完成构建。

生成的 package 不使用 import "C"。c2go-libc 集成 PureGo 原生调用桥,因此消费者可以在 CGO_ENABLED=0、没有宿主 C 编译器的环境中构建;只有生成阶段需要 C2Go 工具链。

C 源码
   │
   ▼
c2go-clang + c2go-lto
   │  Plan 9 汇编 + JSON manifest
   ▼
c2go-bind
   │  生成的 .go + .s package
   ▼
Go 工具链 + c2go-libc

它与普通 C 有什么区别

C2Go 明确区分两个内存世界。当前实现的 translation unit 默认是 unmanaged;通常使用无参数的 #pragma c2go managed push 区域启用全部 managed 默认行为,也可以通过 record/pointer 属性进行局部标注:

  • managed 值参与 Go runtime 的内存模型,并携带精确 GC 元数据;
  • unmanaged 值表示原生 C 内存或外部 C ABI 边界。

这个区别让编译器能够保留精确的 GC 信息。代价是:某些普通 C 中不会检查的操作,如果可能让 GC 看不到指针,在 C2Go 中会产生 warning 或 error。

<c2go.h> 提供的主要扩展包括:

特性 用途
gc_malloc 与 c2go_typeinfo 在 Go heap 上分配带类型的对象
c2go_extern 将已定义的 C 函数导出给 Go
c2go_linkname 将 C 声明绑定到 Go 符号
unmanaged 显式标记原生 C 表示或边界
c2go_callback / c2go_callout 在边界两侧传递可调用函数指针
c2go_returntype 用 C struct 描述 Go 多返回值

每个扩展的完整拼写、类别和限制见 C2Go 扩展速查。

当前版本基线

当前协同版本的基线是:

  • 只支持 C,不支持 C++;
  • 只生成 64 位 amd64 与 arm64 代码;
  • 当前 SDK 支持 Go 1.25.x 与 Go 1.26.x;
  • 每个 OS 与架构分别生成产物;
  • 项目仍处于 pre-1.0,API 与 ABI 细节可能变化。

发布页列出真正构建并测试过的宿主 SDK。迁移现有 C 库前,请阅读平台与当前限制;语言、ABI、回调与打包边界以该页为准。

什么时候适合使用 C2Go

当你希望复用或迁移 C 实现,同时向使用者暴露普通 Go package 时,C2Go 很有价值。对于需要 Go 管理内存、或希望比独立进程边界更深入地接入 Go runtime 的代码尤其如此。

它目前还不能无差别替代所有 cgo 项目。不要因为上游 Clang 能接受某种写法,就默认它已经进入 C2Go 的发布契约;采用前应以链接的限制页为检查清单。

下一步

先安装匹配的 SDK与 Go runtime module,然后在 Hello World 中编译第一个导出 C 函数。