Go, also known as Golang, is a powerful and efficient programming language designed for concurrent systems. However, there might be situations where you need to leverage existing C or C++ libraries, or you want to optimize a critical section of your code using C/C++ for better performance. In this article, we will discuss two common methods for calling C and C++ code from Go: using CGO and SWIG.
CGO is a foreign function interface for Go that allows you to call C code directly from your Go program. CGO provides a way to write C functions that are callable from Go code and vice versa. To use CGO, you need to follow these steps:
To include C code in your Go file, you need to use the import "C"
statement at the beginning of your Go file. Then, you can add your C code within a import "C"
comment block:
package main
// #include <stdio.h>
// #include <stdlib.h>
// void myCFunction() {
// printf("Hello from C code!\n");
// }
import "C"
func main() {
C.myCFunction()
}
To build and run your program with CGO, you need to set the CGO_ENABLED
environment variable to 1
and use the go build
command with the -x
flag:
$ export CGO_ENABLED=1
$ go build -x main.go
$ ./main
You should see the “Hello from C code!” message printed on your console.
SWIG (Simplified Wrapper and Interface Generator) is a powerful tool for creating wrappers around C and C++ code to make it accessible from multiple programming languages, including Go. To use SWIG with Go, you need to follow these steps:
First, you need to install SWIG. You can download it from the official website (http://www.swig.org/) or use a package manager like apt-get
or brew
:
$ sudo apt-get install swig # For Ubuntu/Debian systems
$ brew install swig # For macOS systems
Let’s say you have a simple C++ class Math
that you want to use in your Go program:
// math.h
class Math {
public:
int add(int a, int b);
};
// math.cpp
#include "math.h"
int Math::add(int a, int b) {
return a + b;
}
To use this class in Go, you need to create an interface file (.i
) for SWIG:
// math.i
%module math
%{
#include "math.h"
%}
%include "math.h"
Now, you can generate Go bindings for your C++ code using the following command:
$ swig -c++ -go -intgosize 64 -gccgo math.i
This will generate two files: math.go
and math_wrap.cxx
. The math.go
file contains the Go bindings for your C++ code, and math_wrap.cxx
is the wrapper code that SWIG generates to bridge the gap between Go and C++.
Next, compile your C++ code and the SWIG-generated wrapper code into a shared library:
$ g++ -c -fpic math.cpp math_wrap.cxx -I/usr/local/go/include
$ g++ -shared math.o math_wrap.o -o libmath.so
Now you can use the generated Go bindings in your Go program:
package main
// #cgo CXXFLAGS: -std=c++11
// #cgo LDFLAGS: -L. -lmath
// #include "math_wrap.h"
import "C"
import "fmt"
func main() {
m := C.NewMath()
defer C.DeleteMath(m)
result := C.Math_add(m, 3, 4)
fmt.Printf("3 + 4 = %d\n", int(result))
}
Finally, build and run your Go program using the following commands:
$ export CGO_ENABLED=1
$ export LD_LIBRARY_PATH=.
$ go build main.go
$ ./main
You will see the following output:
3 + 4 = 7