可变可变的可选输出引脚

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

我很不熟悉,一直坚持所有权主题。我以为可以,但是无法使函数中的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板条箱,并且编译器在if let Some区域中失败。我尝试借用了ake_pin,获得了作为参考的选项以及其他一些东西,但是直到现在我还没有完全理解所有权规则。

谢谢

rust
1个回答
3
投票

我相信我已经复制了您的设置。如果有问题,请编辑您的问题以及相关详细信息。

src / 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。如果我们只是借用它,那么使自身背后的数据无效将是很不礼貌的。但是,编译器正在告诉我们一个解决方案。 help: consider borrowing here: `&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();
    }
}
© www.soinside.com 2019 - 2024. All rights reserved.