Since version 2.0, SWIG can support the Go programming language. This makes it possible to write Go programs that invoke C/C++ code. Usually, the C/C++ code and the SWIG-generated C/C++ wrapper code are built into a shared library; the Go invoking code and SWIG-generated Go wrapper code are built into an executable binary, which dynamically links to the shared library.
This solution is good enough unless you are writing a distributed computing program, which will be deployed on many computers with different version of libraries installed. In the context of distributed computing, in order to avoid the complexity of deployment, we usually want to link dependent libraries statically into the binary. However, I found no way to link C/C++ code statically with Go code when I use GC compiler (5g, 6g, 8g etc), because the SWIG-generated C/C++ wrapper code are for Plan 9 C compiler (5c, 6c, 8c etc), which cannot be linked together with the C/C++ library code compiled using GCC.
However, many thanks to Ian Taylor and his GCCGO, the Go frontend for GCC, I can now link Go code with C/C++ code statically. An an example, given a C/C++ implementation of a very simple library (code from SWIG document):
/* File : example.c */
double My_variable = 3.0;
/* Compute factorial of n */
int fact(int n) {
if (n <= 1) return 1;
else return n*fact(n-1);
}
/* Compute n mod m */
int my_mod(int n, int m) {
return(n % m);
}
and corresponding SWIG interface file
/* File : example.i */
%module example
%{
/* Put headers and other declarations here */
extern double My_variable;
extern int fact(int);
extern int my_mod(int n, int m);
%}
extern double My_variable;
extern int fact(int);
extern int my_mod(int n, int m);
we generated C/C++ wrapper code (example_wrap.c) and Go wrapper code (example.go) using SWIG:
swig -go -gccgo example.i
By reading the generated Go code, you would know how to write the caller program. Take the following main.go as an example:
package main
import "fmt"
import "example"
func main() {
fmt.Printf("Hello World:%d\n", example.Fact(3))
}
Let compile all these C/C++ and Go code:
gcc -c example.c -o example_impl.o gcc -c example_wrap.c -o example_wrap.o gccgo -c example.go -o example.o gccgo -c main.go -o main.o
and let link then together (statically):
gccgo main.o example.o example_wrap.o example_impl.o -o hello
Here it is! Now, we can run the generated binary hello and get
Hello World!:6
[...] we can build exisitng code into shared libraries and wrap them using SWIG, as discussed in this post. An alternative to SWIG is to build exisitng code in an RPC [...]