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.