Building shared libraries in Go: Part 1
Summary
Since 1.5, we can write C-style shared libraries (.so
) in Go. These can be used directly from C and C++, but also from any language that can use a C shared library, which is most languages. Here’s the original design document. Let’s do a very simple example and call it from Python. In Part 2 we’ll do a more complex example and call it from C++.
Calling Go from Python
package main
import "C"
//export DoubleIt
func DoubleIt(x int) int {
return x * 2
}
func main() {}
Save that in your GOPATH
as doubler/main.go
. The exported symbols (the functions the shared library provides) must be in a main
package, with a required but ignored main
function. They must be marked with magic comment //export <name>
(no space), because go build
will call cgo.
go build -o libdoubler.so -buildmode=c-shared doubler
This puts libdoubler.so
in your current directory. Let’s check we really have a dynamic shared library:
$ file libdoubler.so
libdoubler.so: ELF 64-bit LSB shared object, x86-64, version 1 (SYSV), dynamically linked ...
$ nm -D libdoubler.so | grep "T DoubleIt"
000000000005d230 T DoubleIt
Well that looks good. Let’s call it from Python, because Python’s ctypes makes this incredibly easy:
>>> import ctypes
>>> lib = ctypes.CDLL("libdoubler.so")
>>> lib.DoubleIt(21)
42
Ta da!
For me this ability to build normal shared libraries makes Go a first-class language on Unix. In later posts we’ll do a more complex example with C++, and time permitting a SWIG example with Ruby.