将数组从Rust返回到FFI
我需要写一个函数,返回一个u16整数数组。然后,FFI应使用此功能将数组从Rust返回到FFI,rust,ffi,Rust,Ffi,我需要写一个函数,返回一个u16整数数组。然后,FFI应使用此功能 extern板条箱libc; 使用libc::{uint16\u t}; #[没有损坏] 发布外部ffi_测试()->*常数16{ let测试:[u16;4]=[1,2,3,4]; test.as_ptr() } Rust代码编译时不会出错。我使用Ruby测试ffi调用: #编码:utf-8 需要“外国金融机构” 模块MyMod 扩展FFI::库 ffi_lib“我的ffi_测试_lib” 附加函数:ffi\U测试,[],:指
extern板条箱libc;
使用libc::{uint16\u t};
#[没有损坏]
发布外部ffi_测试()->*常数16{
let测试:[u16;4]=[1,2,3,4];
test.as_ptr()
}
Rust代码编译时不会出错。我使用Ruby测试ffi调用:
#编码:utf-8
需要“外国金融机构”
模块MyMod
扩展FFI::库
ffi_lib“我的ffi_测试_lib”
附加函数:ffi\U测试,[],:指针
结束
a_ptr=MyMod.ffi_测试
尺寸=4
结果\u数组=一个\u ptr.read\u数组\u的\u uint16(大小)
p结果_数组
但是结果是完全错误的(预期:[1,2,3,4]
):
好像我在读完全不同的记忆地址。我假设我不应该在Rust数组上使用#as_ptr()
编辑
根据@FrenchBoiethios的建议,我尝试将阵列装箱:
extern板条箱libc;
使用libc::{uint16\u t};
#[没有损坏]
发布外部ffi_测试()->*多个uint16_t{
let测试:[u16;4]=[1,2,3,4];
设b=Box::new(测试);
框::输入未加工(b)
}
这会导致编译错误:
note: expected type `std::boxed::Box<u16>`
found type `std::boxed::Box<[u16; 4]>`
注意:应为'std::boxed::Box类型`
找到类型`std::boxed::Box`
您的数组位于堆栈上,因此当您将其作为指针(返回到局部变量的指针)返回时,会出现生存期问题。您必须在堆中分配它:
#[no_mangle]
pub extern "C" fn ffi_test() -> *mut u16 {
let mut test = vec![1, 2, 3, 4];
let ptr = test.as_mut_ptr();
std::mem::forget(test); // so that it is not destructed at the end of the scope
ptr
}
或
我试图学习Rust ffi,这些实现是来自互联网不同来源的弗兰肯斯坦创造的。所以,把它和盐一起吃吧 目前我有两种方法: a) 从rust GC中移除阵列并返回点。用户需要承诺以后免费通话
#[repr(C)]
pub struct V2 {
pub x: i32,
pub y: i32,
}
#[repr(C)]
struct Buffer {
len: i32,
data: *mut V2,
}
#[no_mangle]
extern "C" fn generate_data() -> Buffer {
let mut buf = vec![V2 { x: 1, y: 0 }, V2 { x: 2, y: 0}].into_boxed_slice();
let data = buf.as_mut_ptr();
let len = buf.len() as i32;
std::mem::forget(buf);
Buffer { len, data }
}
#[no_mangle]
extern "C" fn free_buf(buf: Buffer) {
let s = unsafe { std::slice::from_raw_parts_mut(buf.data, buf.len as usize) };
let s = s.as_mut_ptr();
unsafe {
Box::from_raw(s);
}
}
b) 通过FFI回调函数发送数组。用户需要承诺不保留参考资料,但不需要免费拨打电话
#[no_mangle]
pub extern "C" fn context_get_byte_responses(callback: extern "stdcall" fn (*mut u8, i32)) -> bool {
let bytes: Vec<u8> = vec![];
callback(bytes.as_mut_ptr(), bytes.len() as i32);
true
}
#[无损坏]
发布外部“C”fn上下文获取字节响应(回调:外部“stdcall”fn(*mut u8,i32))->bool{
let字节:Vec=Vec![];
回调(bytes.as_mut_ptr(),bytes.len()as i32);
真的
}
您的阵列位于堆栈上。您必须使用向量或框,否则,您将面临终身问题。@FrenchBoiethios感谢您的评论。我更新了问题。有什么提示我该怎么解决这个问题吗?
#[repr(C)]
pub struct V2 {
pub x: i32,
pub y: i32,
}
#[repr(C)]
struct Buffer {
len: i32,
data: *mut V2,
}
#[no_mangle]
extern "C" fn generate_data() -> Buffer {
let mut buf = vec![V2 { x: 1, y: 0 }, V2 { x: 2, y: 0}].into_boxed_slice();
let data = buf.as_mut_ptr();
let len = buf.len() as i32;
std::mem::forget(buf);
Buffer { len, data }
}
#[no_mangle]
extern "C" fn free_buf(buf: Buffer) {
let s = unsafe { std::slice::from_raw_parts_mut(buf.data, buf.len as usize) };
let s = s.as_mut_ptr();
unsafe {
Box::from_raw(s);
}
}
#[no_mangle]
pub extern "C" fn context_get_byte_responses(callback: extern "stdcall" fn (*mut u8, i32)) -> bool {
let bytes: Vec<u8> = vec![];
callback(bytes.as_mut_ptr(), bytes.len() as i32);
true
}