I’ve falling in love with Rust over the last year and a half. I like it for a lot of reasons, a few being the compiler, seperation of noun/verb, and it’s deeply integrated testing. However, recently been thinking through ways to introduce it to the team and the technology portfolio at Fooda.
One idea we had, was move some of our computational intensive tasks to Rust given that is one of it’s “sweet spots” as a technology. However, this left us wondering how exactly would we mix it in with Ruby. Specifically, how do we call Rust from within Ruby.
As it turns out, it’s actually fairly easy to call Rust from within Ruby so long as you understand a few simple things, namely
- C and ABI
With those, and a few lines of code to begin calling Rust from within your Ruby code.
Preparing Rust to be “callable” from Ruby
Ultimately, you don’t need to do a whole lot to make your Rust code available to C.
In fact, here’s a simple
hello world example.
With the code snippet above, you’ll see a couple things different from your typical Rust function. So lets break it down …
#[no_mangle]This tells the Rust compiler to expose this a global function and don’t mangle it with an internal name
extern "C"This exposes the function as if it was a
Cfunction via the
*const libc::c_charOur function returns a
Outside that, our function is a regular Rust function that does it’s thing.
Compile in a slightly different way
Now that your Rust code is exposed prepared properly, we need to ensure
we compile in a manner Ruby can accept, specifically a dynamic library. You can do this two ways, the command line or a Cargo toml file. I’m doing it
through Cargo and a
toml file below
When you execute
Cargo build you will now have a dynamic library
.dylib in your
Including your Rust library in Ruby
If there’s an icky part to this whole process, this is it right here. You’ll need a one-to-one
mapping of the functionality you expose in your Rust dynamic library to your
Here’s an example of how this is done leveraging
Please note, the
path reference above in the
ffi_lib method call is specific to a sample project I’ve
Test drive in IRB
At this point you are able to take it for a test drive in irb.
That’s it. I was incredibly surprised at how easy it was. The only thing I don’t like,
is maintaining that one-to-one mapping in via
ffi in Ruby. A small price to pay, I guess.
Complete working example
I’ve put together a complete working example that will allow you from irb to call into
a Rust module. It’s a
hello world but it works.
It’s found here