当前位置: 首页 > 知识库问答 >
问题:

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

云鸿祯
2023-03-14

我正在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 之外,我还会有更多扫描仪类型,因此,如果我理解正确,我应该使用特征引用 (

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

这不是一个完整的程序;我只粘贴了重要的部分。

我做错了什么,如何在Rust中实现我想要的东西?


共有1个答案

艾焱
2023-03-14

Trait对象必须在指针后面使用。但是引用不是唯一的指针;Box也是一个指针!

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

scanner = match scanner_type {
    ScannerType::Winapi => Some(Box::new(WinapiScanner::new()))
}
 类似资料:
  • 我的情况是,我希望一些对象实现一个特征,比如说“基本”,而其他一些对象将实现一个特征“超级”。Super trait还必须是< code>T : Base的泛型,这样我就可以根据它所专用的Base自动实现Super的各个部分。现在,这似乎可以很好地处理下面的小例子 我的问题与我的下一个要求有关,那就是我希望能够存储实现Super的对象向量,而不管它专门用于哪个Base。我的想法是创建一个涵盖所有超

  • 我当前的Cucumber文件如下所示: 所以现在我想再添加几个场景,可能是在同一个文件中进行API测试。所以我想为此创建一个新特性,而不是使用Feature:Test Online application页面。这样我就不需要为API测试创建单独的特性文件。

  • 将跟踪和跨度添加到Slf4J MDC,以便您可以从日志聚合器中的给定跟踪或跨度中提取所有日志。示例日志: 2016-02-02 15:30:57.902 INFO [bar,6bfd228dc00d216b,6bfd228dc00d216b,false] 23030 --- [nio-8081-exec-3] ... 2016-02-02 15:30:58.372 ERROR [bar,6bfd

  • 反缓存 anticache设置该选项后,它将删除可能引起服务器响应的Header(if-none-match和if-modified-since)304 not modified。当您要确保完全捕获HTTP交换时,这很有用。当您要确保服务器以完整的数据响应时,也经常在客户端重播期间使用它。 客户端重播 客户端重播可以做到:您提供了一个以前保存的HTTP对话,而mitmproxy则一个接一个地重播了

  • 问题内容: 我正在调整我的一个宠物项目以提高其性能。我已经淘汰了探查器以识别热点,但是我认为对Python性能特性的了解要好一些,这将非常有用。 我想知道几件事: 一些现代的编译器拥有非常聪明的优化器,它们通常可以采用简单的代码,并使其运行速度比任何人工调整代码的尝试都要快。根据优化器的智能程度,使我的代码“哑巴”可能更好。 尽管Python是一种“解释”语言,但它确实可以编译为某种形式的字节码(