我使用pyo3Rust crate (0.11.1版)将Rust 代码移植到cpython(3.8.2版)代码中.我创建了一个名为my_class的类,并定义了以下函数:new__str____repr__.

TL;DR:__str__函数存在于使用pyo3 crate 从 rust 迹中移植的类上,但仅使用print(obj)时不会打印,而是必须写入print(obj.__str__())

my_class的定义如下:

use pyo3::prelude::*;

#[pyclass]
struct my_class {
    #[pyo3(get, set)]
    num: i32,
    #[pyo3(get, set)]
    debug: bool,
}

#[pymethods]
impl my_class {
    #[new]
    fn new(num: i32, debug: bool) -> Self {
        my_class {num, debug}
    }
    fn __str__(&self) -> PyResult<String>   {
        Ok(format!("[__str__] Num: {}, Debug: {}", self.num, self.debug))
    }

    fn __repr__(&self) -> PyResult<String> {
        Ok(format!("[__repr__] Num: {}, Debug: {}", self.num, self.debug))
    }
}

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

我构建了它(进入发布模式),并用以下代码测试代码:

from my_module import my_class

def main():
    dsa = my_class(1, True)
    print(dsa)
    print(dsa.__str__())
    
    
if __name__ == "__main__":
    main()

运行测试python代码时,我得到以下输出:

<my_class object at 0x7fb7828ae950>
[__str__] Num: 1, Debug: true

现在我想到了可能的解决办法.一种解决方案可能是pyo3 rust crate 实际上充当代理,为了将类移植到python中,可以实现某种对象,将所有操作转移到移植的类.所以它可能无法实现自己的__str__,因此无法满足我的需求.

感谢阅读到目前为止,希望我能找到一个答案,因为我没有找到任何关于这一点的在线.

推荐答案

我很确定这是因为你需要通过PyObjectProtocol trait个步骤来实现这些方法.

在类型对象的内存布局中,许多Python __magic__方法对应于C级别function pointer slots.在C中实现的类型需要在插槽中提供一个函数指针,Python将自动生成一个方法来包装指针以进行显式方法调用.在Python中实现的类型将自动插入函数指针,将其委托给magic方法.

Python内部通常会查找函数指针,而不是相应的magic方法,如果Python没有找到函数指针,它会表现得好像该方法不存在一样.这就是为什么,例如,必须使用#[new]来标记构造函数,而不是实现__new__静态方法.

__str____repr__也对应于函数指针——具体来说是tp_strtp_repr.如果只是try 将它们作为常规方法实现,pyo3将不会生成所需的函数指针.PyObjectProtocol是pyo3接口.

Rust相关问答推荐

如何装箱生命周期相关联的两个对象?

为什么我不能从带有字符串的 struct 的引用迭代器中收集VEC<;&;str&>?

使用模块中的所有模块,但不包括特定模块

制作一片连续整数的惯用Rust 方法?

如何点击()迭代器?

我是否可以在Ruust中修改 struct 实例上的字符串,以使其在修改后具有相同的字符串生存期?

有没有一种方法可以创建一个闭包来计算Rust中具有随机系数的n次多项式?

如何轮询 Pin>?

为什么 `Deref` 没有在 `Cell` 上实现?

如何以与平台无关的方式将OsString转换为utf-8编码的字符串?

Rust 如何返回大类型(优化前)?

在 Rust 中查找向量中 dyn struct 的索引

trait 对象指针的生命周期

从 Cranelift 发出 ASM

实现不消费的迭代器

Rust - 在线程之间不安全地共享没有互斥量的可变数据

Rust 内联 asm 中的向量寄存器:不能将 `Simd` 类型的值用于内联汇编

如何将 u8 切片复制到 u32 切片中?

如何在 Rust 的内置函数上实现特征?

如果参数为 Send,则返回 Future Send