TL;DR: Call Rust code from Go using FFI
This repository shows how, by combining cgo
and Rust's FFI capabilities, we can call
Rust code from Go.
Two ways of achieving this are presented in this repository: with a dynamic library, and with a static library.
Run make run-all to see Rust + Go in action, building and running two
binaries, one where the Rust code is compiled as a dynamic (sometimes also
referred to as a 'shared') library, and one where it is compiled as a static
library.
You should see the following output:
$ make run-all Compiling libc v0.2.132 Compiling hello v0.1.0 (/home/user/rust-plus-golang/lib/hello) Finished release [optimized] target(s) in 0.1s Hello world! (this is code from the dynamic library) Finished release [optimized] target(s) in 0.00s Hello world! (this is code from the static library)
You will also find the binaries ./main_dynamic and ./main_static in your
current working directory.
The Rust code is packaged up into a dynamic library and a static library, and
the two Go binaries then call these using cgo.
Andrew Oppenlander's article on creating a Rust dynamic library is a great introduction to this topic.
- Begin by creating a
libdirectory, where you will keep your Rust libraries. - Then, create a C header file for your library. See the example
hello.h. - All that is left to do is to add some
cgo-specific comments to your Go code. These comments tellcgowhere to find the library and its headers.
The following cgo comments are required to use a dynamic library:
/* #cgo LDFLAGS: -L./lib -lhello #include "./lib/hello.h" */ import "C"
You must also pass the -ldflags option to go build (see the build-dynamic target in
the Makefile).
See main_dynamic.go
For a static library, an additional -ldl LDFLAGS flag is sometimes
necessary. This flag will link the dl library.
/* #cgo LDFLAGS: ./lib/libhello.a -ldl #include "./lib/hello.h" */ import "C"
There should not be a newline between
*/andimport "C".
See the build-static target in the Makefile and main_dynamic.go.