Python 如何制作一个Rust结构,在不同的线程中修改它自己的值?

Python 如何制作一个Rust结构,在不同的线程中修改它自己的值?,python,rust,pyo3,Python,Rust,Pyo3,我正在使用pyo3制作一个Python模块,用Rust编写,它将: 运行自己的线程 读取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

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

  • 运行自己的线程
  • 读取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(())
}
注意,我必须将结构的
t
类型转换为
选项>
,因为在这里,我需要在创建线程之前创建实例。另外,我的
新的
方法现在返回一个
,而不是只返回
Self
,我不完全确定我是否被允许这样做


我也尝试过使用
Arc
,但是我需要从new返回
Arc
,或者返回
inst_2.lock()
,这将永久地锁定它。

我不知道pyo3,但是你能改为让
count
字段具有type
互斥体吗?我想你可能需要创建一个
[getter]
函数,用于字段提取计数值,而不是直接在字段中使用
#[pyo3(get)]
。@JonasBerlin我最终使用了一个getter函数,并使用了count as
Arc
,就像你说的那样。这是一个多一点的代码,但至少它的工作。我对这个解决方案很满意,但是我想知道,如果你不想处理互斥,你也可以使用原子来处理一个数字,但是对于128位,你需要一个夜间功能。虽然这只是一个递增的计数,但128位的数字是多余的,因为如果计数每纳秒递增一次,填充64位计数器需要500年以上的时间。
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
}