如何处理 Rust 中 impl 方法的静态回调

问题描述 投票:0回答:1

我正在使用 rdev 库来获取用户的键盘输入。我创建了一个名为 InputManager 的类,它有一个像这样的监听方法

use rdev;

struct InputManager {}

impl InputManager {
    pub fn new() -> Self {
        InputManager {}
    }

    fn callback(&mut self, event: rdev::Event) {
        println!("My callback {:?}", event);
        match event.name {
            Some(string) => println!("User wrote {:?}", string),
            None => (),
        }
    }

    pub fn listen(&mut self) -> Result<(), ()> {
        match rdev::listen(|event: rdev::Event| self.callback(event)) {
            Ok(_) => Ok(()),
            Err(_) => Err(()),
        };
        Ok(())
    }
}

fn main() {
    let mut input_manager = InputManager::new();
    input_manager.listen();
}

这会产生以下错误,因为

rdev::listen
函数需要静态回调

  --> src/main.rs:19:15
   |
18 |     pub fn listen(&mut self) -> Result<(), ()> {
   |                   ---------
   |                   |
   |                   `self` is a reference that is only valid in the method body
   |                   let's call the lifetime of this reference `'1`
19 |         match rdev::listen(|event: rdev::Event| self.callback(event)) {
   |               ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
   |               |
   |               `self` escapes the method body here
   |               argument requires that `'1` must outlive `'static`

如何解决这个问题,同时将回调方法保留在类中?

rust callback keyboard-events
1个回答
0
投票

错误消息告诉你,给

listen()
的闭包必须是
'static
,但你的闭包是借用
self
来调用
self.callback()
,而
pub fn listen(&mut self) -> ...
只给你一个更短的临时借用比
'static
。换句话说,当
listen()
调用闭包时,
&self
可能已经无效,因此编译器会拒绝该程序。

答案取决于您想要做什么:您可以将您的方法变成

pub fn listen(self)
(取得所有权)。这将允许
self
移动到闭包中,并且闭包变为
'static
(因为它不包含任何比
'static
短的内容)。缺点是您的
listen()
只能被调用一次,因为需要拥有
InputManager
的所有权才能将该所有权传递给
listen()

另一种方法是将
self
包装成
Rc
(例如
pub fn listen(self: Rc<Self>)
),这也允许
self
作为
'static
值传递。

鉴于

rdev::listen()
似乎是一个全局事件循环,我建议选择第一个选项,并将
pub fn listen(&mut self)
更改为
pub fn listen(self)

© www.soinside.com 2019 - 2024. All rights reserved.