2016-05-23 6 views
4

Ich versuche eine Cairo-Oberfläche in xcb-erstellten Fenster zu verwenden. Ich habe ein C-Beispiel sowie Rust XCB- und Cairo-Bindungen. Ich bin fast fertig, aber dieser Fehler bleibt mir ein Rätsel."lebt nicht lange genug" Fehler beim Aufrufen von `roots` von rost-xcb

Mein Code:

fn find_visual<'a>(conn: &'a xcb::Connection, visual: xcb_visualid_t) -> Option<Visualtype<'a>> { 
    let setup: Setup<'a> = conn.get_setup(); 
    for screen in setup.roots() { 
     let d_iter: DepthIterator = screen.allowed_depths(); 
     for depth in d_iter { 
      for vis in depth.visuals() { 
       if visual == vis.visual_id() { 
        println!("Found visual"); 
        return Some(vis) 
       } 
      } 
     } 
    } 
    None 
} 

Ich nenne dies als:

let visual = find_visual(&conn, screen.root_visual()).unwrap(); 

Und gewinnen Fehler wie folgt aus:

src/main.rs:56:19: 56:24 error: `setup` does not live long enough 
src/main.rs:56  for screen in setup.roots() { 
           ^~~~~ 
src/main.rs:54:97: 68:2 note: reference must be valid for the lifetime 'a as defined on the block at 54:96... 
src/main.rs:54 fn find_visual<'a>(conn: &'a xcb::Connection, visual: xcb_visualid_t) -> Option<Visualtype<'a>> { 
src/main.rs:55  let setup: Setup<'a> = conn.get_setup(); 
src/main.rs:56  for screen in setup.roots() { 
src/main.rs:57   let d_iter: DepthIterator = screen.allowed_depths(); 
src/main.rs:58   for depth in d_iter { 
src/main.rs:59    for vis in depth.visuals() { 
       ... 
src/main.rs:55:45: 68:2 note: ...but borrowed value is only valid for the block suffix following statement 0 at 55:44 
src/main.rs:55  let setup: Setup<'a> = conn.get_setup(); 
src/main.rs:56  for screen in setup.roots() { 
src/main.rs:57   let d_iter: DepthIterator = screen.allowed_depths(); 
src/main.rs:58   for depth in d_iter { 
src/main.rs:59    for vis in depth.visuals() { 
src/main.rs:60     if visual == vis.visual_id() { 
       ... 

Und die gleichen Fehler für screen und depth Variablen.

Kann jemand erklären - warum "setup nicht lange genug lebt"? Wie ich verstehe, setup wird zerstört, wenn Funktion return Option, und es kann in Funktion ohne Einschränkungen verwendet werden.

get_setup() Code:

pub fn get_setup(&self) -> Setup { 
    unsafe { 

     let setup = xcb_get_setup(self.c); 
     if setup.is_null() { 
      panic!("NULL setup on connection") 
     } 
     mem::transmute(setup) 
    } 
} 
+0

Seltsam, die Quelle von rost-xcb betrachtend kann ich keine lebenslangen Annotationen finden; Insbesondere hat die Setup-Struktur keine. –

+0

@SebastianRedl Wie ich Lebenszeiten sehe, existiert http://rtbo.github.io/rust-xcb/src/xcb/xproto.rs.html#1516 – dimcha

+0

Ah, ich schaute auf den veralteten Aatch Repo. –

Antwort

2

Es sieht aus wie die Lebensdauer Anmerkungen der Bindungen fehlerhaft sind. Hier ist roots():

impl<'a> Screen<'a> { 
    pub fn roots(&self) -> ScreenIterator { 
     unsafe { 
      xcb_setup_roots_iterator(self.ptr) 
     } 
    } 
} 

Beachten Sie, dass, weil es keine Anmerkungen auf die Funktion sind, diese implizit als

bezeichnet ist
impl<'a> Screen<'a> { 
    pub fn <'b> roots(&'b self) -> ScreenIterator<'b> { 
     unsafe { 
      xcb_setup_roots_iterator(self.ptr) 
     } 
    } 
} 

Und das ist falsch. Die zurückgegebene ScreenIterator muss explizit mit der Lebenszeit 'a annotiert werden. Dies ist die Lebensdauer der zugrunde liegenden Verbindung, und XCB scheint die Konvention zu haben, dass alle übergebenen Zeiger lebenslang an die Lebensdauer der Verbindung gebunden sind (siehe Kommentar) . für den Wrapper Typ base::StructPtr Dies bedeutet, dass die Generator-Skripte Konto angepasst werden müssen hierfür sollten Sie ein Problem mit der Kiste Datei

upd von Anforderer:... @SebastianRedl richtig war Problem ist in ungesetzt Leben in Xcb Kiste für alle Funktionen, die Iteratoren zurückgibt.Nach Änderungen der Lebensdauer in Rost-Xcb Kiste ermöglicht Code erfolgreich zu kompilieren:

impl<'a> Setup<'a> { 
    pub fn roots(&self) -> ScreenIterator<'a> { 
     unsafe { 
      xcb_setup_roots_iterator(self.ptr) 
     } 
    } 
} 

impl<'a> Depth<'a> { 
    pub fn visuals(&self) -> VisualtypeIterator<'a> { 
     unsafe { 
      xcb_depth_visuals_iterator(self.ptr) 
     } 
    } 
} 

impl<'a> Screen<'a> { 
    pub fn allowed_depths(&self) -> DepthIterator<'a> { 
     unsafe { 
      xcb_screen_allowed_depths_iterator(self.ptr) 
     } 
    } 
} 
+0

Ich habe den xcb ffi Generator geändert und bekomme einen "Fehler: Lebenszeitname' 'a' Schatten einen lebenslangen Namen, der bereits im Geltungsbereich ist ". Es scheint, als könnten wir nicht denselben Lifetime-Namen verwenden wie impl <'a> Screen <'a> – dimcha

+1

Der Punkt ist, dass Sie keine neue Lebensdauer deklarieren sollten, sondern die bestehende verwenden. So sollte es aussehen: "Pub FN Wurzeln (& 'ein Selbst) -> ScreenIterator <'a> {...}", nicht "pub fn Wurzeln <'a> (...)". –