将数组从Rust返回到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测试,[],:指

我需要写一个函数,返回一个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测试,[],:指针
结束
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
}