rust - 不能将 Any 向下转换为包含引用的数组

标签 rust

只传递一个数组似乎工作正常:

fn set_zero<'a>(u: &'a u32, ms: &mut [Option<&'a u32>; 4]) {
    ms[0] = Some(u);
}

我正在尝试包装传递给 void * 的 C 回调函数 所以我使用 std::any::Any 而不是数组:

fn set_zero<'a>(u: &'a u32, ma: &mut Any) {
    if let Some(ms) = ma.downcast_mut::<[Option<&'a u32>; 4]>() {
        ms[0] = Some(u);
    }
}

这会导致与生命周期相关的错误:

error[E0477]: the type `[std::option::Option<&'a u32>; 4]` 
does not fulfill the required lifetime
--> option.rs:18:26
   |
18 |     if let Some(ms) = ma.downcast_mut::<[Option<&'a u32>; 4]>() {
   |                          ^^^^^^^^^^^^
   |
  = note: type must outlive the static lifetime

我该如何解决这个问题?应阅读哪些文档以更好地理解错误?

更新:更详细的背景:

人为设计的 C 原型(prototype)是 - foo.c:

#include <stdint.h>

typedef int (*cb_t)(const uint32_t *obj, void *arg);

int32_t cb_run(uint32_t const objs[], uint32_t len, cb_t cb, void *arg)
{
        int i;
        for (i = 0; i < len; i++)
                if (cb(&objs[i], arg) < 0)
                        return -1;
        return 0;
}

然后,我尝试使用 Any 进行换行:

extern crate libc;
use libc::{c_int, size_t, c_void};
use std::any::Any;

type CbT = extern "C" fn(obj: *const u32, arg: *mut c_void) -> c_int;
extern { fn cb_run(objs: *const u32, len: size_t, cb: CbT, arg: *mut c_void) -> c_int; }

type Cb = fn(obj: &u32, arg: &mut Any) -> i32;
struct CbData <'a> {
    cb: Cb,
    arg: &'a mut Any,
}

extern fn rust_cb(obj: *const u32, arg: *mut c_void) -> c_int {
    unsafe {
        let s = &mut *(arg as *mut CbData);
        (s.cb)(&*obj, s.arg)
    }
}

fn cb_run_rs(objs: &[u32], cb: Cb, arg: &mut Any) -> i32 {
    let mut arg = &mut CbData{ cb: cb, arg: arg } ;
    unsafe { cb_run(objs.as_ptr() as *const u32, objs.len() as size_t,
                    rust_cb, arg as *mut _ as *mut c_void) as i32 }
}

//// the above is lib, the below is bin

// set_zero() in the above
fn my_cb<'a>(obj: &'a u32, arg: &mut Any) -> i32 {
    if let Some(data) = arg.downcast_mut::<[Option<&'a u32>; 4]>() {
        data[0] = Some(obj);
    }
    0
}

fn main() {
    let objs = [0u32, 1, 2, 3];
    let mut arg = [None; 4];
    println!("pre  : {:?}", arg);
    cb_run_rs(&objs, my_cb, &mut arg);
    println!("post : {:?}", arg);
}

它导致注意:类型必须比静态生命周期长。 在没有来自库用户的 unsafe 的情况下,如何以良好的方式处理这种 void *

最佳答案

我只能说它似乎有效。主.rs

extern crate libc;
use libc::{c_int, size_t, c_void};

type CbT = extern "C" fn(obj: *const u32, arg: *mut c_void) -> c_int;
extern { fn cb_run(objs: *const u32, len: size_t, cb: CbT, arg: *mut c_void) -> c_int; }

type Cb <'a, T: ?Sized> = fn(obj: &'a u32, arg: &mut T) -> i32;
struct CbData <'a, 'b, T: 'a + 'b + ?Sized> {
    cb: Cb<'a, T>,
    arg: &'b mut T,
}

extern fn rust_cb<T: ?Sized>(obj: *const u32, arg: *mut c_void) -> c_int {
    unsafe {
        let s = &mut *(arg as *mut CbData<T>);
        (s.cb)(&*obj, s.arg)
    }
}

fn cb_run_rs<'a, 'b, T: 'a + ?Sized>(objs: &[u32], cb: Cb<'a, T>, arg: &'b mut T) -> i32 {
    let mut arg = &mut CbData{ cb: cb, arg: arg } ;
    unsafe { cb_run(objs.as_ptr() as *const u32, objs.len() as size_t,
                    rust_cb::<T>, arg as *mut _ as *mut c_void) as i32 }
}

//// the above is lib, the below is bin

fn my_cb<'a>(obj: &'a u32, arg: &mut [Option<&'a u32>]) -> i32 {
    arg[*obj as usize] = Some(obj);
    0
}

fn main() {
    let objs = [0u32, 1, 2, 3];
    let mut arg = [None; 4];
    println!("pre  : {:?}", arg);
    cb_run_rs(&objs, my_cb, &mut arg);
    println!("post : {:?}", arg);
}

仅供引用 build.rs:

extern crate gcc;

fn main() {
    gcc::compile_library("libfoo.a", &["src/foo.c"]);
}

cargo .toml:

[package]
name = "sof"
version = "0.1.0"
authors = ["author@example.com"]
build = "build.rs"

[build-dependencies]
gcc = "0.3"

[dependencies]
libc = "0.2"

关于rust - 不能将 Any 向下转换为包含引用的数组,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/40922855/

相关文章:

reference - `mut a: &T` 和 `a: &mut T` 有什么区别?

for-loop - Rust 中 for 循环的命名中断

rust - 在Rust中将文本数字解析为UTF-8字符?

rust - `#[cfg(test)]` 和 `#[cfg(feature = "test")]` 有什么区别?

rust - 参数位置中的 dyn Trait 是什么意思?

rust - 根据同一 Vec 的其他元素删除 Vec 元素的最佳方法

rust - 如何在 .cargo/config 文件中使用环境变量?

rust - 将 &i64 转换为 &[u8; 的惯用方法是什么? 8]?

arrays - 如何将一个 800 行 25 列的文件存储在一个 N 维数组中?

rust - 使用 std::ptr::set_memory 时出现未解析的名称错误