你可以,但最好的問題是應該你?
既然你不能在C構建一個Vec
,你必須建立它在鏽,然後返回一個指向下的C代碼將自己的指針Vec
,然後將其傳回調用do_something_else
時。
然後存在的問題是,您無法真正修改C中的Vec
,除了創建新的FFI方法來鏡像所有Rust方法。
你也可能不應該採取,因爲鏽病引用保證不爲NULL,並沒有什麼強制執行,從C.調用時最好是採取*const Vec<i32>
,斷言它的非NULL和將其轉換爲參考。
很可能您希望通過FFI邊界接受C數組。 C數組的指針和長度,所以你會同時接受並重組防鏽片(因爲你沒有自己的數組):
use std::slice;
pub extern fn do_something_else(p: *const i32, len: libc::size_t) {
let slice = unsafe {
assert!(!p.is_null());
slice::from_raw_parts(p, len)
};
}
強制性鏈接The Rust FFI Omnibus。
如果你真的需要做的,你問什麼的話,大概是這個樣子:
extern crate libc;
#[no_mangle]
pub extern fn make_vec() -> *mut Vec<i32> {
Box::into_raw(Box::new(Vec::new()))
}
#[no_mangle]
pub extern fn add_number(vec: *mut Vec<i32>, val: libc::int32_t) {
let vec = unsafe {
assert!(!vec.is_null());
&mut *vec
};
vec.push(val);
}
#[no_mangle]
pub extern fn print_vec(vec: *const Vec<i32>) {
let vec = unsafe {
assert!(!vec.is_null());
&*vec
};
println!("{:?}", vec);
}
#[no_mangle]
pub extern fn drop_vec(vec: *mut Vec<i32>) {
unsafe {
assert!(!vec.is_null());
Box::from_raw(vec);
}
}
,並會使用類似(未經測試):
// Add extern declarations
int main(int argc, char *argv[]) {
void *v = make_vec(); // Use a real typedef here
add_number(v, 42);
print_vec(v);
drop_vec(v);
}
你想在valgrind下運行,以確保我沒有做任何愚蠢的記憶方式。
我認爲你可以將整數數組指針傳遞給C中的生鏽函數,然後你可以使用矢量切片來完成操作。 – noshusan
@noshusan你的意思是做一些像'pub extern fn do_thing(slice:&[i32])'然後在C方聲明它像'void do_thing(int32_t slice [])''? –
我不確定,但是你可以做一些像'pub extern fn do_thing(slice:* [i32])'這樣的聲明在c面,像'void do_thing(int32_t * slice [])'一樣。這裏你使用的是raw_pointer,所以你必須聲明一個不安全的塊。 – noshusan