2016-12-02 27 views
1

只是傳遞一個數組的數組似乎很好地工作:不能垂頭喪氣任何使用包含引用

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

我想包被傳遞一個void * 所以我用std::any::Any而不是C回調函數

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 
0123的陣列的

我該如何解決這個問題?應該閱讀哪些文檔以更好地理解錯誤?

UPDATE:更詳細的背景:

一種做作C原型是 - 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); 
} 

它會導致note: type must outlive the static lifetime。 如何處理這種void *沒有來自庫用戶的unsafe

+1

'Any'不是'無效*' – Shepmaster

+2

反正看了一個合理的等價['Any' docs]的第一段(https://doc.rust-lang.org/std/any/index.html):*可以通過動態輸入**任何靜態類型**運行時反射。* - 您的類型不是靜態的。 – Shepmaster

+0

就像你說的那樣。我意識到我誤解了''static'是編譯時已知的類型。我能否認爲這是「Any」與「void *」的合理等同的一個原因? – chamaken

回答

0

我只能說它似乎工作。 main.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); 
} 

FYI 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 = ["[email protected]"] 
build = "build.rs" 

[build-dependencies] 
gcc = "0.3" 

[dependencies] 
libc = "0.2"