简体   繁体   English

一生难忘

[英]Caught between a lifetime and an FFI place

I am caught between two different issues/bugs, and can't come up with a decent solution. 我陷入了两个不同的问题/错误之间,无法提出一个体面的解决方案。 Any help would be greatly appreciated 任何帮助将不胜感激

Context, FFI, and calling a lot of C functions, and wrapping C types in rust structs. 上下文,FFI和调用许多C函数,并将C类型包装在rust结构中。

The first problem is ICE: this path should not cause illegal move . 第一个问题是ICE:此路径不应引起非法移动

This is forcing me to do all my struct-wrapping using & references as in: 这迫使我使用&引用执行所有结构包装,如下所示:

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

Instead of the simpler, and preferable: 而不是更简单,更可取的:

pub struct CassResult {
    result:cql_ffi::CassResult
}

Otherwise code like: 否则代码如下:

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

Will result in: 将导致:

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

So, I go ahead and wrap everything using lifetime managed references, and all is not-horrible until I try to implement an iterator. 因此,我继续使用生命周期管理的引用包装所有内容,直到尝试实现迭代器,所有内容都不会令人恐惧。 At which point I see no way around this problem . 在这一点上,我认为没有办法解决这个问题

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

So given those two conflicting issues, I am totally stuck and can't find any way to implement a proper rust iterator around a FFI iterator-like construct. 因此,鉴于这两个相互矛盾的问题,我完全陷入了困境,无法找到任何方法来围绕类似FFI迭代器的构造实现适当的rust迭代器。

Edit: With Shep's suggestion, I get: 编辑:在谢普的建议下,我得到:

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

and

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})
}}

but then get: 但然后得到:

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

Is there any way to make that pattern work? 有什么办法可以使该模式起作用? It's repeated all over this FFI wrapping code. 在此FFI包装代码中重复了所有步骤。

Only a partial answer: use the "streaming iterator" trait and macro . 仅部分回答:使用“流迭代器”特征和宏

I have had a similar problem making Rust bindings around the C mysql API. 我在围绕C mysql API进行Rust绑定时遇到了类似的问题。 The result is code like this, instead of native for syntax: 结果是这样的代码,而不是本机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));
});

Here res holds the result and frees memory on drop. res保留结果,并释放内存。 The lifetime of row is tied to 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){
        ...
    }
}

To answer my own question. 回答我自己的问题。 The only decent answer was a way around the original ICE , but as thepowersgang comments, the correct way to do this now is to use :std::ptr::read, so using that approach, no ICE, and hopefully progress. 唯一合理的答案是围绕原始ICE的一种方法,但是正如powersgang所评论的那样,现在执行此操作的正确方法是使用:std :: ptr :: read,因此使用该方法,无需ICE,并有望取得进展。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM