2

我正在使用 pyo3 制作一个用 Rust 编写的 Python 模块,它将:

  • 运行自己的线程
  • 读取 Raspberry Pi 上的输入引脚,计算状态更改的次数
  • 让 Python 查询计数器

到目前为止,我的代码如下所示:

use std::thread;

use pyo3::prelude::*;

#[pyclass]
struct CountWatcher {
    // The number of the GPIO pin we'll be watching
    // Can't be read from Python
    pin: u8,

    // How many times the pin changed state
    // Can be read from Python
    #[pyo3(get)]
    count: u128,

    // Thread handle
    t: thread::JoinHandle<()>,
}

#[pymethods]
impl CountWatcher {
    #[new]
    fn new(pin: u8) -> Self {
        let t = thread::spawn(|| {
            loop {
                // This is where the code that reads the GPIO pin, and increments count will eventually go
                println!("Test");
                std::thread::sleep(std::time::Duration::from_secs(1));
            }
        });

        Self {
            pin,
            count: 0,
            t: t,
        }
    }
}

#[pymodule]
fn countwatcher(_py: Python, m: &PyModule) -> PyResult<()> {
    m.add_class::<CountWatcher>()?;
    Ok(())
}

这段代码有效,但我遇到的问题是以某种方式获取线程内实例的引用,以便我可以更新count,同时仍然让 Pythoncount随时检查。

我认为这样的事情会起作用,但它没有:

fn new(pin: u8) -> Arc<Self> {
    let mut inst = Self {
        pin,
        count: 0,
        t: None,
    };

    let mut inst_1 = Arc::new(inst);
    let mut inst_2 = inst_1.clone();

    let t = thread::spawn(move || {
        loop {
            inst_1.count += 1;
            std::thread::sleep(std::time::Duration::from_secs(1));
        }
    });

    inst_2.t = Some(t);

    inst_2
}

请注意,我必须将结构的t类型转换为Option<thread::JoinHandle()>>,因为在这里,我需要在创建线程之前创建实例。另外,我的new方法现在返回 anArc<Self>而不是 just Self,我不完全确定我是否可以这样做。

我也尝试过使用Arc<Mutex<CountWatcher>>,但是我需要Arc<Mutex<CountWatcher>>从新返回一个,或者返回inst_2.lock(),这只会永久锁定它。

4

0 回答 0