Compile C into Go packages without cgo.

Compile C source into importable Go packages with C2Go, a Clang-based ahead-of-time toolchain that runs code in the Go runtime and builds without cgo.

  • PureGo · CGO_ENABLED=0
  • Go GC aware
  • C ABI interop
C source
→
c2go-clang
→
Plan 9 + JSON
→
c2go-bind
→
Go package
c2go-libcC runtime compatibility for the Go runtime environment
C input
#include <c2go.h>

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

result := translated.Add(20, 22)

C2Go

A C-to-Go compiler toolchain, not a source rewriter

C2Go is a Clang-based ahead-of-time compilation mode for reusing or migrating existing C implementations as ordinary Go packages. It emits Plan 9 assembly for the Go assembler and a structured manifest, then c2go-bind generates a package the Go toolchain can build directly.

It does not promise to rewrite arbitrary C into hand-maintained Go source. C remains the implementation language while the compiled result uses goroutine stacks, Go scheduling, and an optional GC-aware memory model.

Build without cgo

Generated packages do not depend on import "C". c2go-libc uses a PureGo native-call bridge so consumers can build with CGO_ENABLED=0 and no host C compiler.

Get started
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-aware allocation

Explicitly managed records can be allocated on the Go heap through c2go-libc. Type information lets the GC scan their pointer layout precisely.

Get started
C sourceanswer = go_answer(21);
call →
Go symbolfunc Answer(v int32) int32

Call Go from C

Declare Go symbols with c2go_linkname, call them directly from C, and let the compiler preserve the ABI boundary.

Get started
native.c
extern double vendor_scale(double);

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

Call native libraries

Declared-only functions automatically import system or third-party C ABIs. c2go-bind records linker inputs in the final Go package.

Get started
native APIregister_cb(callback);
← callback
C2Go functionc2go_callback(on_value)

Callbacks across the boundary

Wrap C2Go-compiled functions as native function pointers or explicitly import host addresses for real C callback APIs.

Get started

From C to Go in minutes

1

Install

Download the SDK for your host and pin the matching c2go-libc version.

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

Compile

c2go-clang emits Plan 9 assembly and a 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

Bind

c2go-bind assembles the artifacts into a normal Go package.

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

Current SDK platforms

Linuxamd64
Linuxarm64
Windowsamd64
macOSarm64

iRelease candidate; binaries are unsigned and APIs and ABI details may still change.

C2Go frequently asked questions

Does C2Go rewrite C as Go source?

It is not a general source-to-source rewriter. c2go-clang compiles C, and c2go-bind generates the .go and .s files that make up an ordinary Go package.

Does the final Go package require cgo?

No. Generation requires the C2Go SDK, but consumers can build with CGO_ENABLED=0 and without a host C compiler.

Which code and platforms are supported?

The current candidate targets C, not C++. Published SDKs cover Linux amd64/arm64, Windows amd64, and macOS arm64. Review the language, ABI, callback, and stack-pointer limits before adoption.

Is C2Go production-ready?

The current build is a pre-1.0 release candidate. Binaries are unsigned, and APIs and ABI details may change, so it is intended for evaluation, compatibility testing, and controlled migrations.

Start with Hello World

Begin with one C addition function, then learn GC-managed memory, interop, and multi-file builds.

Get started