Search docsSearch this language
Interoperability
Release candidatev0.20260809.0-rc.5

These docs describe the current coordinated release candidate.

Interoperability

Call Go from C

Bind C declarations to Go symbols and model Go multi-value returns.

c2go_linkname binds a C declaration to a named Go symbol. The C signature is the compiler’s ABI description of that Go function, so it must match exactly.

Bind a normal Go function

Suppose package example.com/mathx contains:

package mathx

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

Declare and call it from 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);
}

For an ordinary Go function, omit the optional ABI selector. C2Go creates an alias and wrapper that bridge to the Go internal ABI.

Symbols in the current package

The C declaration always spells the complete Go symbol name. Clang then uses -fc2go-package to decide whether that target belongs to the package being generated. Compiling the example above with -fc2go-package=example.com/mathx resolves example.com/mathx.Double to a package-local LLVM and Plan 9 symbol instead of a cross-package reference. The complete linkname remains in IR and manifest metadata for auditing and generation checks.

Do not pass the import path to c2go-bind again. The binder reads it from the manifest; use the optional --pkgname override only when the Go source package name differs from the path base.

Bind an existing ABI0 symbol

Use C2GO_GOABI0 only when the target already exposes a Go ABI0 entry point:

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

This selector requests a direct reference rather than a generated internal-ABI bridge. It is not a general performance switch. <c2go.h> already exposes this runtime entry as gc_malloc; the alias above only illustrates the ABI selector and should not replace that public API.

Receive multiple Go results

Describe one Go result slot per C struct field:

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);

The fields become independent Go ABI result slots; C2Go does not pass a hidden sret pointer. Every field must fit one supported slot: a scalar, pointer, floating-point value, or supported C2Go aggregate.

Functions and variables

c2go_linkname can bind both functions and variables. In either case, the complete Go symbol name in the C declaration and -fc2go-package are build contracts. Refactoring the Go package or symbol without updating them together produces a link failure.

Current boundary

For C ABI libraries rather than Go symbols, use native library imports.