PHP FFI - return 数组 rom Rust 函数返回 PHP

PHP FFI - return array rom Rust function back to PHP

我需要 return 来自 rust 函数的几个值。试图声明 return 数组

的函数
$ffi = FFI::cdef('float get_arr()[2];', './target/release/libphp_rust.dylib');

$array = $ffi->get_arr();

但是出现错误: PHP Fatal error: Uncaught FFI\ParserException: function returning array is not allowed at line 1 in /array.php:3

似乎PHP FFI 不能直接使用数组。所以我找到了另一个解决方案。 我从 PHP 创建了 C 数组,然后将指向它的指针传递给 Rust 代码,然后用 Rust 函数填充它:

$ffi = FFI::cdef('bool get_arr(float (*res)[2]);', './target/release/libphp_rust.dylib');

$array = $ffi->new('float[2]');

$result = $ffi->get_arr(FFI::addr($array));

if ($result) {
    var_dump($array);
} else {
    //... something went wrong
}
#[no_mangle]
pub extern fn get_arr(array_pointer: *mut [f32;2]) -> bool {
    let res = unsafe {
        assert!(!array_pointer.is_null());
        &mut *array_pointer
    };

    res[0] = 0.1;
    res[1] = 0.2;

    return true;
}

这个解决方案似乎工作正常,但我对此有一些疑问:

  1. 将指针传递给 FFI 是否足够安全,我将来可能会遇到什么问题?
  2. Rust 数组是否完全兼容 C,以便我能够通过索引直接为其赋值?
  3. 我有更好的方法来实现我所需要的吗?或者是否有一些关于使用 FFI 传递复杂数据结构的良好实践?

谢谢

围绕此的规则仍然悬而未决,因此您的示例是否安全值得怀疑。这应该没问题,但需要夜间功能:

#![feature(maybe_uninit_extra)]
#![feature(ptr_as_uninit)]

// Make sure you use `extern "C"`. `extern` alone means `extern "Rust"`.
#[no_mangle]
pub extern "C" fn get_arr(array_pointer: *mut [f32; 2]) -> bool {
    let fat: *mut [f32] = array_pointer;
    let res = unsafe { fat.as_uninit_slice_mut().unwrap() };

    res[0].write(0.1);
    res[1].write(0.2);

    true
}

在稳定频道上就没那么优雅了:

// Make sure you use `extern "C"`. `extern` alone means `extern "Rust"`.
#[no_mangle]
pub extern "C" fn get_arr(array_pointer: *mut [f32; 2]) -> bool {
    assert!(!array_pointer.is_null());
    unsafe {
        let res = array_pointer as *mut f32;
        res.add(0).write(0.1);
        res.add(1).write(0.2);
    }

    true
}