简体   繁体   English

Rust和特征引用(特征对象?)中的多态性

[英]Polymorphism in Rust and trait references (trait objects?)

I'm writing a process memory scanner with a console prompt interface in Rust. 我正在用Rust的控制台提示符界面编写过程内存扫描器。

I need scanner types such as a winapi scanner or a ring0 driver scanner so I'm trying to implement polymorphism. 我需要诸如winapi扫描仪或ring0驱动程序扫描仪之类的扫描仪,因此我正在尝试实现多态。

I have the following construction at this moment: 目前,我的结构如下:

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();
    }
}

In future, I'll have some more scanner types besides WinapiScanner , so, if I understand correctly, I should use a trait reference ( &Scanner ) to implement polymorphism. 将来,除了WinapiScanner之外,我WinapiScanner拥有更多其他扫描仪类型,因此,如果我理解正确,我应该使用特征引用( &Scanner )实现多态。 I'm trying to create Scanner object like this (note the comments): 我正在尝试创建这样的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())
}

It's not a full program; 这不是一个完整的程序; I've pasted important parts only. 我只粘贴了重要部分。

What am I doing wrong and how do I implement what I want in Rust? 我在做什么错,如何在Rust中实现我想要的?

Trait objects must be used behind a pointer. 特性对象必须在指针后面使用。 But references are not the only kind of pointers; 但是引用并不是唯一的指针。 Box is also a pointer! Box也是指针!

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

scanner = match scanner_type {
    ScannerType::Winapi => Some(Box::new(WinapiScanner::new()))
}

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM