2017-04-22 13 views
1

私はRustにコンソールプロンプトインタフェースを持つプロセスメモリスキャナを書いています。錆と形質の多型(形質オブジェクト?)

多態性を実装しようとしているので、winapiスキャナやring0ドライバスキャナなどのスキャナタイプが必要です。

私は現時点では次のような構成があります。将来的には

pub trait Scanner { 
    fn attach(&mut self, pid: u32) -> bool; 
    fn detach(&mut self); 
} 

pub struct WinapiScanner { 
    pid: u32, 
    hprocess: HANDLE, 
    addresses: Vec<usize> 
} 

impl WinapiScanner { 
    pub fn new() -> WinapiScanner { 
     WinapiScanner { 
      pid: 0, 
      hprocess: 0 as HANDLE, 
      addresses: Vec::<usize>::new() 
     } 
    } 
} 

impl Scanner for WinapiScanner { 
    fn attach(&mut self, pid: u32) -> bool { 
     let handle = unsafe { OpenProcess(PROCESS_ALL_ACCESS, FALSE, pid) }; 
     if handle == 0 as HANDLE { 
      self.pid = pid; 
      self.hprocess = handle; 
      true 
     } else { 
      false 
     } 
    } 

    fn detach(&mut self) { 
     unsafe { CloseHandle(self.hprocess) }; 
     self.pid = 0; 
     self.hprocess = 0 as HANDLE; 
     self.addresses.clear(); 
    } 
} 

を、私はWinapiScanner以外にいくつかのより多くのスキャナタイプを持っていますので、私が正しく理解していれば、私は形質参照(&Scanner)を使用する必要があります多型を実装する。私はこのようなScannerオブジェクト(コメントに注意してください)を作成しようとしています:

enum ScannerType { 
    Winapi 
} 

pub fn start() { 
    let mut scanner: Option<&mut Scanner> = None; 
    let mut scanner_type = ScannerType::Winapi; 

    loop { 
     let line = prompt(); 
     let tokens: Vec<&str> = line.split_whitespace().collect(); 
     match tokens[0] { 

      // commands 
      "scanner" => { 
       if tokens.len() != 2 { 
        println!("\"scanner\" command takes 1 argument") 
       } else { 
        match tokens[1] { 
         "list" => { 
          println!("Available scanners: winapi"); 
         }, 
         "winapi" => { 
          scanner_type = ScannerType::Winapi; 
          println!("Scanner type set to: winapi"); 
         }, 
         x => { 
          println!("Unknown scanner type: {}", x); 
         } 
        } 
       } 
      }, 
      "attach" => { 
       if tokens.len() > 1 { 
        match tokens[1].parse::<u32>() { 
         Ok(pid) => { 
          scanner = match scanner_type { 
           // ---------------------- 
           // Problem goes here. 
           // Object, created by WinapiScanner::new() constructor 
           // doesn't live long enough to borrow it here 
           ScannerType::Winapi => Some(&mut WinapiScanner::new()) 
           // ---------------------- 
          } 
         } 
         Err(_) => { 
          println!("Wrong pid"); 
         } 
        } 
       } 
      }, 

      x => println!("Unknown command: {}", x) 
     } 
    } 
} 

fn prompt() -> String { 
    use std::io::Write; 
    use std::io::BufRead; 

    let stdout = io::stdout(); 
    let mut lock = stdout.lock(); 
    let _ = lock.write(">> ".as_bytes()); 
    let _ = lock.flush(); 
    let stdin = io::stdin(); 
    let mut lock = stdin.lock(); 
    let mut buf = String::new(); 
    let _ = lock.read_line(&mut buf); 
    String::from(buf.trim()) 
} 

それは完全なプログラムではありませんが。私は重要な部分だけを貼り付けました。

私は間違っていると私はどのように私は錆にしたい実装するのですか?

答えて

5

特徴オブジェクトは、ポインタの後ろに使用する必要があります。しかし、参照だけがポインタの種類ではありません。 Boxもポインタです!

let mut scanner: Option<Box<Scanner>> = None; 

scanner = match scanner_type { 
    ScannerType::Winapi => Some(Box::new(WinapiScanner::new())) 
} 
関連する問題