rust - 可变的可选 OutputPin

标签 rust

我被所有权困住了;我却做不到 Option<OutputPin>在我的功能中可用。应该如何?

struct Chip {
    wake_pin: Option<OutputPin>,
}

impl Chip {
    pub fn new(wake_pin: Option<Pin>) -> Chip {
        Chip {
            wake_pin: wake_pin.map(|pin| pin.into_output()),
        }
    }

    pub fn awake(&self) {
        // Fails
        if let Some(pin) = self.wake_pin {
            pin.set_low();
        }
    }
}

fn main() {
    let wake_pin = Gpio::new()
        .expect("Can not init gpio")
        .get(255)
        .expect("Could not attach to wake pin");

    let chip = Chip::new(Some(wake_pin));
}

我正在使用 rppal crate,编译器在 if let Some 中失败区域。我试着借wake_pin , 得到 Option作为引用和其他一些东西,但我不完全理解所有权规则。

最佳答案

我相信我已经复制了您的设置。如果有什么地方不对,请使用相关详细信息编辑您的问题。

源/main.rs:

use rppal::gpio::{Gpio, OutputPin, Pin};

struct Chip {
    wake_pin: Option<OutputPin>,
}

impl Chip {
    pub fn new(wake_pin: Option<Pin>) -> Chip {
        Chip {
            wake_pin: wake_pin.map(|pin| pin.into_output()),
        }
    }

    pub fn awake(&self) {
        // Fails
        if let Some(pin) = self.wake_pin {
            pin.set_low();
        }
    }
}

fn main() {
    let wake_pin = Gpio::new()
        .expect("Can not init gpio")
        .get(255)
        .expect("Could not attach to wake pin");

    let chip = Chip::new(Some(wake_pin));
}

cargo .toml:

[package]
name = "tmp"
version = "0.0.1"
edition = "2018"

[dependencies]
rppal = "0.11.3"

尝试编译它(使用 cargo check 或类似的),我们收到警告和两个错误。

warning: unused variable: `chip`
  --> src/main.rs:28:9
   |
28 |     let chip = Chip::new(Some(wake_pin));
   |         ^^^^ help: consider prefixing with an underscore: `_chip`
   |
   = note: `#[warn(unused_variables)]` on by default

error[E0507]: cannot move out of `self.wake_pin.0` which is behind a shared reference
  --> src/main.rs:16:28
   |
16 |         if let Some(pin) = self.wake_pin {
   |                     ---    ^^^^^^^^^^^^^ help: consider borrowing here: `&self.wake_pin`
   |                     |
   |                     data moved here
   |                     move occurs because `pin` has type `rppal::gpio::pin::OutputPin`, which does not implement the `Copy` trait

error[E0596]: cannot borrow `pin` as mutable, as it is not declared as mutable
  --> src/main.rs:17:13
   |
16 |         if let Some(pin) = self.wake_pin {
   |                     --- help: consider changing this to be mutable: `mut pin`
17 |             pin.set_low();
   |             ^^^ cannot borrow as mutable

error: aborting due to 2 previous errors

Some errors have detailed explanations: E0507, E0596.
For more information about an error, try `rustc --explain E0507`.
error: Could not compile `tmp`.

To learn more, run the command again with --verbose.

由于您稍后可能会使用 chip,我们可以通过暂时将其重命名为 _chip 来消除警告。

let _chip = Chip::new(Some(wake_pin));

第一个错误告诉我们不能将引脚移出 self,因为我们只是借用了 self。如果我们只是借用它,那么使 self 后面的数据无效是相当粗鲁的。然而,编译器告诉我们一个解决方案。 帮助:考虑在这里借用:`&self.wake_pin`

虽然不太对,但方向是对的。

if let Some(pin) = &self.wake_pin {
    pin.set_low();
}

现在,pin 的类型不再是 OutputPin(拥有的值),而是类型 &OutputPin(借用的值)。

虽然我们仍然遇到第二个错误(措辞略有不同)。重点是 pin.set_low() 要求 pin 成为可变引用。现在,我们将 self 作为不可变引用 (pub fn awake(&self))。如果我们要改变 self 或其任何字段,我们需要对其进行可变处理。这也意味着我们需要确保可变借用 pin

pub fn awake(&mut self) {
    if let Some(pin) = &mut self.wake_pin {
        pin.set_low();
    }
}

关于rust - 可变的可选 OutputPin,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/58366181/

相关文章:

windows - 从Rust Windows二进制条板箱导出功能

pointers - 为什么断言 Deref::deref 的结果会因类型不匹配而失败?

rust - 如何在类型上而不是在类型内部使用自定义命名空间派生宏属性?

rust - Mutex 可以引用结构但不能引用原语

time - 如何在 Rust 中对程序进行基准测试?

rust - slice_mut 为 &mut [T]

c - 如何处理将 usize 传递给需要 uint32_t 的 C 函数?

testing - 如何在不要求参数函数可变的情况下测试元函数?

rust - 将字符转换为大写

task - 将 Vec<Struct> 传递到新任务中