Statically Link C++ Code With Go Code

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
About these ads

One Response to Statically Link C++ Code With Go Code

  1. [...] 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 [...]

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Connecting to %s

Follow

Get every new post delivered to your Inbox.

%d bloggers like this: