Это несколько уместно, но ответ мне не совсем понятен:
Библиотека C освобождает указатель от Rust
Там также есть пример со статической строкой в книге, однако, он не будет правильно работать с динамически создаваемой строкой.
Я наконец пришел к этому решению, когда вызов кода на C / C ++ выделяет, а затем освобождает память для получаемой строки, но это выглядит несколько уродливо и должно определить некоторую конкретную длину для неизвестной строки:
#[no_mangle]
pub extern fn rs_string_in_string_out(s_raw: *const c_char, out: *mut c_char) -> c_int {
// take string from the input C string
if s_raw.is_null() { return 0; }
let c_str: &CStr = unsafe { CStr::from_ptr(s_raw) };
let buf: &[u8] = c_str.to_bytes();
let str_slice: &str = std::str::from_utf8(buf).unwrap();
let str_buf: String = str_slice.to_owned();
//produce a new string
let result = String::from(str_buf + " append from Rust");
let len = result.len();
//create C string for output
let c_result = CString::new(result);
//write string into out pointer passed by C++ addon
unsafe{ std::ptr::copy(c_result.unwrap().as_ptr(), out, len); };
// return result length
return len as c_int;
}
Было бы неплохо иметь что-то, что действительно возвращает значение, а не записывать в изменяемый аргумент.
Вы можете использовать into_raw
на CString
превратить его в необработанный указатель, который вы затем можете вернуть из своей функции.
Вы не должны полагаться на Rust, используя системный распределитель. Там нет гарантии, что ваш код Rust будет ссылаться на тот же free
как код C / C ++. В Windows, например, есть msvcrt
, msvcr80
, msvcr90
и т. д., и все они управляют отдельными кучами. Следовательно, ваша библиотека должна по-прежнему предоставлять функцию для освобождения памяти, которую она выделяет. За CString
, вы должны использовать CString::from_raw
для этого (вам не нужно использовать результат, Rust автоматически удалит его, что освободит строку в куче).
Не уверен, что это совершенно новый, но документация гласит (https://doc.rust-lang.org/book/custom-allocators.html#default-allocator), что библиотеки используют alloc_system по умолчанию, что означает, что мы можем свободно использовать free в C / C ++. Также возможно добавить #! [Feature (alloc_system)] в заголовок, чтобы чувствовать себя безопаснее.