1
votes

I'm trying to call a function which accepts a string, written in Rust.

The Rust code is then compiled to C and included in my Ruby code via the FFI gem.

When I call the Rust function and pass a string I get nothing.

Rust code:

#[no_mangle]
pub extern fn speak(words: &str) {
  println!("{}", words);
}

Ruby code:

require 'ffi'

module Human
  extend FFI::Library
  ffi_lib '../target/release/libruby_and.dylib'
  attach_function :speak, [:string], :void
end

Human.speak("Hello, we are passing in an argument to our C function!!")
1
Have you seen The Rust FFI Omnibus?Shepmaster

1 Answers

4
votes

According to the documentation, :string represents a null-terminated string, which is char * in C. The &str argument is not equivalent to that type: a &str is a compound value, composed of a pointer and a length.

The safest solution is to change your Rust function to accept a *const c_char instead. You can then use CStr::from_ptr and CStr::to_str to work with it more easily.

Alternatively, you could define a struct in your Ruby code that contains a pointer and a length, and pass that to the Rust function. However, there's no guarantee that this struct will always match the memory layout of a slice, so to be 100% safe, you should define the equivalent struct in your Rust code (with #[repr(C)]), then, using the fields of this struct, call slice::from_raw_parts to construct a slice (&c_char or &u8), which you can then turn into a &str with str::from_utf8.