将数组从 Rust 返回到 FFI

Ern*_*est 6 ffi rust

我需要编写一个在 Rust 中返回 u16 整数数组的函数。FFI 应该使用该函数。

extern crate libc;
use libc::{uint16_t};

#[no_mangle]
pub extern fn ffi_test() ->  *const uint16_t {
    let test: [u16;4] = [1,2,3,4];

    test.as_ptr()
}
Run Code Online (Sandbox Code Playgroud)

Rust 代码编译没有错误。我使用 Ruby 来测试 ffi 调用:

# coding: utf-8
require 'ffi'

module MyMod
  extend FFI::Library
  ffi_lib 'my_ffi_test_lib'
  attach_function :ffi_test, [], :pointer
end

a_ptr = MyMod.ffi_test
size = 4
result_array = a_ptr.read_array_of_uint16(size)
p result_array
Run Code Online (Sandbox Code Playgroud)

但结果完全错误(预期[1, 2, 3, 4]:):

$ ruby ffi_test.rb
[57871, 25191, 32767, 0]
Run Code Online (Sandbox Code Playgroud)

好像我正在读取完全不同的内存地址。我想也许我不应该#as_ptr()在 Rust 数组上使用?

编辑

根据 @FrenchBoiethios 的建议,我尝试将数组装箱:

$ ruby ffi_test.rb
[57871, 25191, 32767, 0]
Run Code Online (Sandbox Code Playgroud)

这会给出编译错误:

note: expected type `std::boxed::Box<u16>`
         found type `std::boxed::Box<[u16; 4]>`
Run Code Online (Sandbox Code Playgroud)

Fre*_*ios 4

您的数组位于堆栈上,因此当您将其作为指针返回(返回指向局部变量的指针)时,会出现生命周期问题。您必须在堆中分配它:

#[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
}
Run Code Online (Sandbox Code Playgroud)

或者

#[no_mangle]
pub extern "C" fn ffi_test() -> *mut u16 {
    let test = Box::new([1u16, 2, 3, 4]);  // type must be explicit here...

    Box::into_raw(test) as *mut _          // ... because this cast can convert
                                           // *mut [i32; 4] to *mut u16
}
Run Code Online (Sandbox Code Playgroud)

  • 堆上数组的内存是如何释放的? (2认同)