在一生和FFI之间徘徊

时间:2015-01-28 03:12:28

标签: rust ffi lifetime

我遇到了两个不同的问题/错误,并且无法找到合适的解决方案。任何帮助将不胜感激

Context,FFI,调用很多C函数,并在生锈结构中包装C类型。

第一个问题是ICE: this path should not cause illegal move

这迫使我使用&进行所有结构包装。引用如下:

pub struct CassResult<'a> {
    result:&'a cql_ffi::CassResult
}

而不是更简单,更可取:

pub struct CassResult {
    result:cql_ffi::CassResult
}

否则代码如下:

pub fn first_row(&self) -> Result<CassRow,CassError> {unsafe{
    Ok(CassRow{row:*cql_ffi::cass_result_first_row(self.result)})
}}

将导致:

error: internal compiler error: this path should not cause illegal move
Ok(CassRow{row:*cql_ffi::cass_result_first_row(self.result)})
               ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

所以,我继续使用生命周期管理引用来包装所有内容,在我尝试实现迭代器之前,所有内容都不是很糟糕。在这一点上,我看不到this problem

method next has an incompatible type for trait: expected concrete lifetime, found bound lifetime parameter

因此,鉴于这两个相互矛盾的问题,我完全陷入困境,无法找到任何方法在类似FFI迭代器的构造周围实现适当的生锈迭代器。

编辑:根据Shep的建议,我得到:

pub struct CassResult {
    pub result:cql_ffi::CassResult
}

pub fn get_result(&mut future:future) -> Option<CassResult> {unsafe{
    let result:&cql_ffi::CassResult = &*cql_ffi::cass_future_get_result(&mut future.future);
    Some(CassResult{result:*result})
}}

然后得到:

error: cannot move out of borrowed content
Some(CassResult{result:*result}

有没有办法让这种模式有效?它已经在这个FFI包装代码上重复了。

2 个答案:

答案 0 :(得分:0)

只有部分答案:使用"streaming iterator" trait and macro

我遇到类似的问题,围绕C mysql API制作Rust绑定。结果是这样的代码,而不是本机for语法:

let query = format!("SELECT id_y, value FROM table_x WHERE id = {}", id_x);
let res = try!(db::run_query(&query));
streaming_for!( row, res.into_iter(), {
    let id_y: usize = try!(row.convert::<usize>(0));
    let value: f64 = try!(row.convert::<f64>(1));
});

这里res保存结果并释放内存。 row的生命周期与res

相关联
/// Res has an attached lifetime to guard an internal pointer.
struct Res<'a>{ p: *mut c_void }
/// Wrapper created by into_iter()
struct ResMoveIter<'a>{ res: Res<'a> }
impl<'a> /*StreamingIterator<'a, Row<'a>> for*/ ResMoveIter<'a>{
    /// Get the next row, or None if no more rows
    pub fn next(&'a mut self) -> Option<Row<'a>>{
        ...
    }
}
#[unsafe_destructor]
impl<'a> Drop for Res<'a>{
    fn drop(&mut self){
        ...
    }
}

答案 1 :(得分:0)

回答我自己的问题。唯一合适的答案是围绕原始ICE的方式,但正如thepowersgang评论,现在正确的方法是使用:std :: ptr :: read,所以使用这种方法,没有ICE,并希望进展。