Строка становится пустой, проходя через FFI от ржавчины до рубина - PullRequest
1 голос
/ 15 марта 2019

У меня есть rubygem с собственным расширением, написанным на ржавчине.

Собственное расширение поддерживает сериализацию своей структуры данных в JSON.

Однако, хотя я и подтвердил, что генерирует JSON,строка всегда пуста на стороне рубина.

Вот код рубина:

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

И код ржавчины

/// 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
}

На стороне Rust println! Использование подтверждает, что указатель содержит строку JSON.

Сравнивая адрес, который он печатает, с возвращаемым значением #export в ruby, я вижу, что используется тот же указатель.

Однако, вызов get_bytes(0, 10) для указателя показывает, что онначинается с нулевых байтов, и попытка преобразовать его в строку возвращает пустую строку.

Я подозреваю, что он обнуляется, потому что время жизни переменных истекло, и я строю в режиме отладки;однако мне не ясно, что мне нужно изменить.

1 Ответ

2 голосов
/ 15 марта 2019

Разобрался - мне нужно было использовать CString::into_raw на стороне ржавчины, чтобы предотвратить его очистку.

...