PHP FFI-将数组函数返回给PHP

PHP FFI-将数组函数返回给PHP,php,rust,ffi,php-ffi,Php,Rust,Ffi,Php Ffi,我需要从rust函数返回几个值。试图声明返回数组的函数 $ffi = FFI::cdef('float get_arr()[2];', './target/release/libphp_rust.dylib'); $array = $ffi->get_arr(); 但有一个错误: PHP致命错误:未捕获FFI\ParserException:在/array.PHP:3中的第1行不允许函数返回数组 PHP FFI似乎无法直接处理数组。所以我找到了另一个解决办法。 我从PHP创建了C-ar

我需要从rust函数返回几个值。试图声明返回数组的函数

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

$array = $ffi->get_arr();
但有一个错误:
PHP致命错误:未捕获FFI\ParserException:在/array.PHP:3中的第1行不允许函数返回数组

PHP FFI似乎无法直接处理数组。所以我找到了另一个解决办法。 我从PHP创建了C-array,然后将指向它的指针传递给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
}
这个解决方案似乎是正确的,但我对此有些怀疑:

  • 传递指向外国金融机构的指针是否足够安全?将来我可能会面临哪些问题
  • Rust数组是否完全C兼容,以便我能够通过索引直接为其赋值
  • 我有没有更好的方法来实现我所需要的?或者,关于使用FFI传递复杂数据结构,是否有一些好的做法

  • 谢谢

    围绕这一点的规则仍然悬而未决,因此您的示例无疑是安全的。这应该可以,但需要夜间功能:

    #![功能(可能不需要添加)]
    #![功能(ptr_as_uninit)]
    //确保使用'extern“C``extern`单独的意思是“extern”Rust`。
    #[没有损坏]
    发布外部“C”fn get_arr(数组指针:*mut[f32;2])->bool{
    让fat:*mut[f32]=数组_指针;
    设res=unsafe{fat.as_uninit_slice_mut().unwrap()};
    res[0]。写入(0.1);
    res[1]。写入(0.2);
    真的
    }
    
    在稳定通道上,它只是不那么优雅:

    //确保使用'extern“C'``extern`单独的意思是“extern”Rust`。
    #[没有损坏]
    发布外部“C”fn get_arr(数组指针:*mut[f32;2])->bool{
    assert!(!array_pointer.is_null());
    不安全{
    设res=array_指针为*mut f32;
    res.add(0)。write(0.1);
    决议添加(1)。写入(0.2);
    }
    真的
    }
    
    请您解释一下,我们需要这条线做什么<代码>让fat:*mut[f32]=数组\u指针当然,这只是为了使用该方法而将
    *mut[f32;2]
    强制为
    *mut[f32]
    (胖指针)。无论出于何种原因,Rust似乎不会自动执行此操作。如果需要,您可以删除该行并使用以下命令设置
    res
    let res=unsafe{::as\u uninit\u slice\u mut(数组指针).unwrap()。我被这件事难住了,做了更多的挖掘,结果是!好的,明白了。。。还有一个问题。。。如果我非常确定数组应该只有2个值,为什么我需要胖指针呢?在这种特殊情况下,使用胖指针而不是指向固定大小数组的指针有什么好处吗?我是一个新手,对所有这些指针的东西都会生锈,所以我只是想抓住要点。谢谢
    
    #[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;
    }