C library freeing a pointer coming from Rust
我想对需要回调的C库进行Rust绑定,并且此回调必须返回指向C库的C样式
从某种意义上讲,回调必须暴露给我的库用户(可能使用闭包),并且我想提供一个尽可能方便的Rust接口(意味着如果可能接受
但是,C库在尝试
所以目前我可以看到使用
- 给图书馆用户一个他必须填写的切片(不方便,并施加了长度限制)
-
取得他的
String 输出,将其复制到malloc分配的数组中,然后释放String (无用的复制和分配)
有人能找到更好的解决方案吗?
这里等效于C库的接口,并且是理想情况的实现(如果C库可以释放在Rust中分配的String)
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 | extern crate libc; use std::ffi::CString; use libc::*; use std::mem; extern"C" { // The second parameter of this function gets passed as an argument of my callback fn need_callback(callback: extern fn(arbitrary_data: *mut c_void) -> *mut c_char, arbitrary_data: *mut c_void); } // This function must return a C-style char[] that will be freed by the C library extern fn my_callback(arbitrary_data: *mut c_void) -> *mut c_char { unsafe { let mut user_callback: *mut &'static mut FnMut() -> String = mem::transmute(arbitrary_data); //' let user_string = (*user_callback)(); let c_string = CString::new(user_string).unwrap(); let ret: *mut c_char = mem::transmute(c_string.as_ptr()); mem::forget(c_string); // To prevent deallocation by Rust ret } } pub fn call_callback(mut user_callback: &mut FnMut() -> String) { unsafe { need_callback(my_callback, mem::transmute(&mut user_callback)); } } |
C部分等效于此:
1 2 3 4 5 6 | #include <stdlib.h> typedef char* (*callback)(void *arbitrary_data); void need_callback(callback cb, void *arbitrary_data) { char *user_return = cb(arbitrary_data); free(user_return); // Complains as the pointer has been allocated with jemalloc } |
这可能需要您进行一些烦人的工作,但是如何公开实现
这是当前与
1 2 | let mut v = Vec::new(); write!(&mut v,"hello, world"); |
您"只是"需要实现这两种方法,然后您将拥有一个类似于流的接口。