Interaction with C and C++

Go lets its users write programs in combination with Go and C/C++. This lesson covers how a Go program can have functionalities of C and C++ imported in it.

We'll cover the following

Interacting with C

The cgo program provides the mechanism for FFI-support (Foreign Function Interface) to allow safe calling of C libraries from Go code. Here is the link to the primary cgo documentation. The cgo replaces the normal Go-compilers, and it outputs Go and C files that can be combined into a single Go package. It is good practice to combine the calls to C in a separate package. The following import is then necessary in your Go program:

import "C"

and usually also:

import "unsafe"

You can include C-libraries (or even valid C-code) by placing these statements as comments (with // or /* */) immediately above the import "C" line:

// #include <stdio.h>
// #include <stdlib.h>
import "C"

C is not a package from the standard library, and it is simply a special name interpreted by cgo as a reference to C’s namespace. Within this namespace exist the C types denoted as C.uint, C.long, and so on, and functions like C.random() from libc can be called. Variables in the Go program have to be converted to the C type when used as parameters in C functions, and vice-versa. For example:

var i int
C.uint(i) // from Go int to C unsigned int
int(C.random()) // from C long (random() gives a long type number) to Go int

In the above snippet, variable i is a Go type variable, which is converted to C type by C.unit() function. Then, in the next line, we create a random number of type C using C.random() function, which is then converted to Go type using int() function.

Strings do not exist as explicit type in C, which means to convert a Go string s to its C equivalent use:

C.CString(s)

The reverse is done with the function:

C.GoString(cs)

where cs is a C string. Memory allocations made by C code are not known to Go’s memory manager, so they are not garbage collected. It is up to the developer to free the memory of C variables with C.free, as follows:

defer C.free(unsafe.Pointer(Cvariable))

This line best follows the line where Cvariable is created to make sure the memory release happens at the end of the scope.

Interacting with C++

SWIG (Simplified Wrapper and Interface Generator) (see documentation) support exists for calling C++ and C code from Go on Linux. Using SWIG is a bit more involved:

  • Write the SWIG interface file for the library to be wrapped.
  • SWIG will generate the C stub functions.
  • These can then be called using cgo, doing so the Go files are automatically generated as well.

This interface handles overloading, multiple inheritance, and allows us to provide a Go implementation for a C++ abstract class.


That is all about interacting with C and C++. The next lesson includes some helpful resources to catch up with Golang.

Get hands-on with 1400+ tech skills courses.