String becomes empty passing through FFI from rust to ruby

烈酒焚心 提交于 2021-01-28 13:55:36

问题


I have a rubygem with a native extension written in rust.

The native extension supports serializing its data-structure to JSON.

However, whilst I've confirmed it's generating JSON, the string is always empty on the ruby side.

Here's the ruby code:

module RustCuckooFilter
  extend FFI::Library
  ffi_lib 'libcuckoofilter_cabi'

  class Instance < FFI::AutoPointer
    def export(path)
      RustCuckooFilter.export(self)
    end
  end

  attach_function :export, :rcf_cuckoofilter_export, [Instance], :pointer

And the rust code

/// Exports the filter to a file
#[no_mangle]
pub extern "C" fn rcf_cuckoofilter_export(filter: *mut rcf_cuckoofilter) -> *const c_char {
    let filter = unsafe { filter.as_mut() };
    let serialized = serde_json::to_string(&filter.expect("Given rcf_cuckoofilter* is a null pointer").export()).unwrap();
    let cstr = CString::new(serialized).expect("JSON was not a valid c string");
    let ptr = cstr.as_ptr();
    unsafe {
        println!("{:#?}", ptr);
        println!("{}", CStr::from_ptr(ptr).to_str().expect("validity"));
    }
    ptr
}

On the Rust side, the println! use confirms that the pointer contains a JSON string.

By comparing the address it prints with the return value of #export in ruby I can see that the same pointer is used.

However, calling get_bytes(0, 10) on the pointer reveals that it starts with null bytes, and attempting to convert it to a string returns an empty string.

I suspect that it's getting zeroed out because the variables lifetime is over and I'm building in debug mode; however, I'm not clear what I'd need to change.


回答1:


Figured it out - I needed to use CString::into_raw on the rust side to prevent it getting cleaned up.



来源:https://stackoverflow.com/questions/55173958/string-becomes-empty-passing-through-ffi-from-rust-to-ruby

标签
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!