2016-07-19 18 views
0

私はRustの初心者です。マンデルブロットのようなフラクタルをレンダリングする簡単なアプリケーションを作りたいと思います。フラクタルはX11ウィンドウにレンダリングされます。 X11ウィンドウはxcb crate(バージョン0.7.4)で作られています。変数に構造体の変数を埋め込む

構造体のウィンドウに必要なものすべてをカプセル化したいと思います。私は何とか接続オブジェクトと同じ寿命を持っている接続から設定オブジェクトを必要とする構造体のための私のnew機能で

extern crate xcb; 
use xcb::base::*; 

struct FbWindow { 
    conn: Connection, 
    window: u32, 
    gc: u32, 
    width: u16, 
    height: u16, 
    fb: Vec<u8> 
} 

impl FbWindow { 
    fn new(width: u16, height: u16) -> FbWindow 
    { 
     let (conn, screen_nr) = Connection::connect(None).unwrap(); 
     let setup = conn.get_setup(); 
     let screen = setup.roots().nth(screen_nr as usize).unwrap(); 
     let root = screen.root(); 

     /* Create GC - graphics context */ 
     let gc = conn.generate_id(); 
     let gc_values = [ 
      (xcb::GC_FOREGROUND, screen.black_pixel()), 
      (xcb::GC_GRAPHICS_EXPOSURES, 0) 
     ]; 
     xcb::create_gc(&conn, gc, root, &gc_values); 

     /* Create window */ 
     let window = conn.generate_id(); 
     let window_values = [ 
      (xcb::CW_BACK_PIXEL, screen.black_pixel()), 
      (xcb::CW_EVENT_MASK, xcb::EVENT_MASK_EXPOSURE | xcb::EVENT_MASK_KEY_PRESS) 
     ]; 
     xcb::create_window(&conn, xcb::COPY_FROM_PARENT as u8, window, root, 
      0, 0, width, height, 1, xcb::WINDOW_CLASS_INPUT_OUTPUT as u16, 
      screen.root_visual(), &window_values 
     ); 
     xcb::map_window(&conn, window); 

     /* Create the framebuffer */ 
     let mut fb : Vec<u8> = vec![0; (width as usize) * (height as usize) * 4]; 

     FbWindow { 
      conn: conn, 
      window: window, 
      gc: gc, 
      width: width, 
      height: height, 
      fb: fb 
     } 
    } 
} 

コンパイラは、接続オブジェクトをnewによって返される構造体オブジェクトに移動させません。私も構造にsetupを追加しようとしましたが、それは助けにはなりません。コンパイラは上記のコードでは、次のエラー得られます

セットアップの種類についてのドキュメントを探し
src/main.rs:46:19: 46:23 error: cannot move out of `conn` because it is borrowed [E0505] 
src/main.rs:46    conn: conn, 
           ^~~~ 
src/main.rs:18:21: 18:25 note: borrow of `conn` occurs here 
src/main.rs:18   let setup = conn.get_setup(); 
            ^~~~ 

を、

type Setup<'a> = StructPtr<'a, xcb_setup_t>; 

私は錆や寿命の概念には本当に新しいですし、それはだが明らかに私にはまだ分かりませんが、私が理解している限り、setupの寿命はconnであり、借用のためにコンパイラはsetupに移動しません。

コードを意図どおりに動作させるにはどうすればよいですか?

編集:このコードは、crate repository の例をベースにしています。編集2:newの完全なソースコード。

+0

おそらくhttp:// stackoverflowの複製です。com/q/32300132 – Shepmaster

+0

@malbarbo例へのリンクを追加しました – fsasm

+0

@fsasmここで質問する質問は[mcve]になると予想されます。本物の問題を持つコードへのオフサイトリンクを提供することは、将来誰にも役立たず、再現するのに十分な情報を提供しないため、この質問を閉じる理由になる可能性があります。 – Shepmaster

答えて

2

私たちはすべてこれについて頭を傷つけました。ほとんどの場合、コンパイラは何が間違っているかを伝えます。

ライン18で、あなたはconnを借りている:

let setup = conn.get_setup(); 

はほとんどのメソッドは、このように彼らは上と呼ばれているオブジェクトを借りて、彼らの最初の引数として&selfまたは&mut selfを取ります。メソッドが何も返さない場合、借用はそのスコープの最後で終了します。 setupが生涯('a in Setup<'a>)を使用しているため、借用期間が延長されるため、ここでは該当しません。これはあなたが望むように多くの不変の借用を持つことができるので、通常はあなたのやり方では得られませんが、少なくとも1つ所有している限り、所有している変数は移動できません。

だから! setupが存在する限り、コンパイラはconnの移動を許可しません。これを修正するには、構造体を作成する前にセットアップが "死ぬ"ことを確認する必要があります。あなたはブロックがサビでの表現であるという事実を利用することができます代わりに初期化されていない変数を宣言するの、また

fn new(width: u16, height: u16) -> FbWindow 
{ 
    let (conn, screen_nr) = Connection::connect(None).unwrap(); 

    // because of block scoping, you might want to declare variables here 
    let gc: u32; 
    ... 

    { 
     // Borrowing `conn` here... 
     let setup = conn.get_setup(); 
     let screen = setup.roots().nth(screen_nr as usize).unwrap(); 
     ... 

     // Assign to the on the outer scope 
     gc = ...; 

     // All variables declared within this block will drop here, 
    } 

    // `conn` is not borrowed anymore! 

    FbWindow { 
     conn: conn, 
     window: window, 
     gc: gc, 
     width: width, 
     height: height, 
     fb: fb 
    } 
} 

、最後に解決します。それを行うための簡単な方法は、そのようなブロックでそれを周りにラップすることですそれにライン。タプルにパックして、パターンマッチングで分解することができます。

let (window, gc, fb) = { 
    ... 

    // no semicolon here 
    (0, 0, Vec::new()) 
} 
+0

あなたが提案したようにブロックを試しましたが、同じエラーメッセージが表示されます。 – fsasm

+0

'conn'の生涯に' setup'が結びついていて、 'conn'の完全な存続期間中に借用が存在するため、あなたの解決策は機能しないと思います。 – fsasm

+0

変更したコードをどこかに貼り付けることはできますか? 'setup'は実際に' conn'の存続期間に縛られています。 'setup'が範囲外になると、借用は終了します。私が構造体の他のすべての値は 'Copy'なので、他には' conn'を借りることはできません。 – Maciej

関連する問題