With the release of Go 1.5 we got access to a
new buildmode called c-shared
, which allows you to build shared libraries that
Ruby-FFI can load. (Also, anything else that can load shared libraries)
Inspiration
Filippo Valsorda has already written a very nice article on Building Python modules with Go 1.5 but I naturally wanted to use Ruby instead of Python.
Requirements
You will need to have Go and Ruby installed. (I am using Go 1.5 and Ruby 2.2.3 in this article)
Getting started
Our library is going to perform the complicated task of adding up two integers, and then returning the resulting sum.
Break out your trusty editor and type in the following code:
libsum.go
package main
import "C"
//export add
func add(a, b int) int {
return a + b
}
func main() {}
Note: The only callable symbols will be those functions exported using a cgo
//export
comment. Non-main packages are ignored.
Building the shared library
We are now ready to use the c-shared
buildmode in order to build the shared library:
go build -buildmode=c-shared -o libsum.so libsum.go
Using Ruby-FFI to load libsum.so
So what is this Ruby-FFI thing you keep talking about?
Info: Ruby-FFI is a ruby extension for programmatically loading dynamic libraries, binding functions within them, and calling those functions from Ruby code.
Ok, cool.
Install the ffi
gem:
$ gem install ffi
Fetching: ffi-1.9.10.gem (100%)
Building native extensions. This could take a while...
Successfully installed ffi-1.9.10
1 gem installed
Now you are ready to interface with libsum.so
require 'ffi'
module Sum
extend FFI::Library
ffi_lib './libsum.so'
attach_function :add, [:int, :int], :int
end
puts Sum.add(15, 27) #=> 42
Well, look at that!
Wait, what about memory management?
There is a section on memory management in the FFI wiki.
You probably also want to read C? Go? Cgo!
Bonus round: Binding directly from Crystal (No need for FFI)
@[Link(ldflags: "-L. -lsum")]
lib Sum
fun add(a : Int32, b : Int32) : Int32
end
puts Sum.add(15,27) #=> 42