Using Go code in an existing C project

To build an archive callable from C, you will need to mark them as exported CGo symbols.
For example, if I create a file foo.go with the following contents:

package main

import (
    "C"
    "fmt"
)

//export PrintInt
func PrintInt(x int) {
    fmt.Println(x)
}

func main() {}

The important things to note are:

  • The package needs to be called main
  • You need to have a main function, although it can be empty.
  • You need to import the package C
  • You need special //export comments to mark the functions you want callable from C.

I can compile it as a C callable static library with the following command:

go build -buildmode=c-archive foo.go

The results will be an archive foo.a and a header foo.h. In the header, we get the following (eliding irrelevant parts):

...
typedef long long GoInt64;
...
typedef GoInt64 GoInt;
...
extern void PrintInt(GoInt p0);
...

So that’s enough to call the exported function. We can write a simple C program that calls it like so:

#include "foo.h"

int main(int argc, char **argv) {
    PrintInt(42);
    return 0;
}

We can compile it with a command like:

gcc -pthread foo.c foo.a -o foo

The -pthread option is needed because the Go runtime makes use of threads. When I run the resulting executable it prints 42.

Leave a Comment