使用 Ruby FFI 调用 Rust 库时出现分段错误

Segmentation fault when calling a Rust lib with Ruby FFI

我想将 String 传递给 Rust 库,但它总是抛出分段错误。

代码如下:

 // lib.rs
 #[no_mangle]
 pub extern fn process(foo: String) -> String {
     foo
 }

和 Ruby 文件:

 # embed.rb
 require 'ffi'

 module Hello
   extend FFI::Library
   ffi_lib 'target/release/libembed.dylib'
   attach_function :process, [ :string ], :string
 end

 puts Hello.process("foo")

发生这种情况是因为 Ruby 和 Rust 中 "string" 的定义不匹配。

Ruby FFI 期望它是来自 C 的 char*,即指向字符数组的指针(see herecreate_object 函数)。所以 Ruby 试图将它解引用为指针以获取字符数据但失败了,因为它不是真正的指针。

Rust 有自己的 String class,它不仅仅是来自 C 的 char*。以指针形式从 Rust 导出字符串是棘手且通用的,足以 deserve a separate question, and this answer应该能帮到你。

免责声明:我以前从未使用过Ruby-FFI;我将继续我可以在文档中找到的内容。

根据 Ruby-FFI wiki page on types:string 等同于以 NUL 结尾的 C 字符串。 与 Rust String 不同。 Rust 中的 String(目前)大三倍!

Rust 中对应的类型是 *const ::libc::c_char。值得注意的是,还有 std::ffi::CString, which is designed for creating C strings, and std::ffi::CStr 是安全包装器类型,可以从 a CString*const c_char 创建。请注意 这些都不兼容 *const c_char!

总而言之,要在 Rust 中处理 C 字符串,您将不得不兼顾类型。另请记住,根据您实际尝试执行的操作,您可能还需要使用 libc::malloclibc::free.

手动管理内存

This answer to "Rust FFI C string handling" 提供了有关如何在 Rust 中处理 C 字符串的更多详细信息。尽管问题的上下文是与 C 代码集成,但它对您的情况应该同样有用。