Skip to Content
marmot

New

cgo support is new. Cross builds of cgo packages are not supported yet.

Packages that import "C" build unchanged. marmot runs cmd/cgo and compiles the generated code and the package's .c, .s and .S files with clang. #cgo CFLAGS, LDFLAGS and pkg-config lines work, and are checked against the same allowlists as the go command.

package main

/*
#include <stdlib.h>
#include <string.h>

static int twice(int x) { return 2 * x; }
*/
import "C"

import (
	"fmt"
	"unsafe"
)

func main() {
	s := C.CString("marmot")
	defer C.free(unsafe.Pointer(s))
	fmt.Println(C.strlen(s), C.twice(21))
}

Cheaper calls

A call to a C function is a direct native call with the C ABI, on the goroutine's own stack. There is no argument frame and no switch to another stack. The runtime is told when a goroutine enters and leaves C so the scheduler can keep other goroutines running; for functions marked with both #cgo noescape and #cgo nocallback, and for libc leaf functions, even that is reduced to a mark.

cost of one call to an empty C functionmarmotgo (cgo)
linux/amd64, -release2.3 ns33 to 57 ns

In release builds the C code is compiled to LLVM bitcode and optimized together with the Go code, so small C functions can be inlined into Go.

What works

  • C functions, variables, constants, structs, unions, arrays, enums and function pointers.
  • C.CString, C.GoString, C.GoStringN, C.GoBytes, C.CBytes, C.malloc and C.free.
  • The errno second result.
  • //export: C calling Go, including nested calls, blocking callbacks and threads created in C.
  • marmot test of cgo packages.
  • Blocking C calls do not stop other goroutines.

Not yet

  • Cross builds (-target) of cgo packages.

A fault inside a C call stops the program with a fatal error.

On this page

Was this page helpful?

Report an issueOpen issues