[英]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.