2015-01-28 10 views
1

나는 두 가지 다른 문제/버그 사이에 끼어 들고 괜찮은 해결책을 찾을 수 없습니다. 모든 도움을 크게 주시면 감사하겠습니다.평생과 FFI 장소 사이에 붙잡음

컨텍스트, 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 반복자와 같은 구조의 주위에 적절한 녹 반복자를 구현할 수있는 방법을 찾을 수 없습니다.

편집 : 셉의 제안으로, 내가 얻을 :

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 배치 코드 전체에서 반복됩니다.

+0

작업하고자하는 전체 코드를 제공하면이 문제에 대한 의견을 제시하는 것이 더 쉽습니다. 나는 Stack Overflow가 이것을 알아 내기위한 좋은 장소가 아니라고 생각한다. Rust IRC 채널을 사용해 보는 것이 좋습니다. –

+0

첫 번째 버그의 해결 방법으로 먼저 참조를 거쳐야 할 수 있습니다. 'foo : T = unsafe {* ptr} '대신'foo : & mut T = unsafe {& mut * ptr}'(명확성을 위해 중복 된 주석을 추가)를 시도해보십시오. – Shepmaster

+0

나는 이런 식으로 달렸다고 생각하는데, 나는 당신이'CassResult' 일 것이라고 추측 한 타입에 대해'Copy'를 구현함으로써 특정한 경우에 해결할 수있었습니다. –

답변

0

내 자신의 질문에 대답하기 위해. 괜찮은 대답은 원래 ICE 주위의 방법 이었지만, 권자 주석으로 사용하는 올바른 방법은 std :: ptr :: read를 사용하는 것입니다. 따라서이 접근법을 사용하고 ICE가 없으면 잘 진행됩니다.

0

부분 응답 : "streaming iterator" trait and macro 만 사용하십시오.

C mysql API에서 녹스 바인딩을 만드는 비슷한 문제가있었습니다. 결과는 대신 기본 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){ 
     ... 
    } 
} 
+0

ICE가 수정되기를 정말로 바라는 반면 스트리밍 반복기 아이디어를 좋아합니다. 시도해보고 작동하면이 대답을 받아 들일 것입니다. 텔레비젼 –