0x00 开篇
Rust 可以与很多语言交互,前面我们已经介绍过与 C# 、JavaScript,本篇文章将继续介绍 Rust 如何与 Python 交互。
0x01 在 Rust 中是使用不同类型
当我们在调用 Rust 函数时,PyO3 会将作为函数参数传递的 Python 类型转换为 Rust 类型。并且它还将 Rust 函数返回的 Rust 类型转换为可在 Python 中使用的类型。下表是常见的包含 Python 类型和将接受它们的相应函数参数类型:
| Python | Rust 锈 | Rust (Python-native) Rust(Python 原生) |
|---|---|---|
str | String, Cow<str>, &str, OsString, PathBuf String 、 Cow<str> 、 &str 、 OsString 、 PathBuf | &PyUnicode |
bytes | Vec<u8>, &[u8], Cow<[u8]> Vec<u8> 、 &[u8] 、 Cow<[u8]> | &PyBytes |
bool | bool | &PyBool |
int | Any integer type (i32, u32, usize, etc) 任何整数类型( i32 、 u32 、 usize 等) | &PyLong |
float | f32, f64 f32 , f64 | &PyFloat |
list[T] | Vec<T> | &PyList |
tuple[T, U] | (T, U), Vec<T> (T, U) , Vec<T> | &PyTuple |
下面是一个向 rust 函数中传递一个数组,经过排序后并返回结果:
use pyo3::prelude::*;
/// 排序
#[pyfunction]
fn sort(mut vec: Vec<isize>) -> PyResult<Vec<isize>> {
vec.sort();
Ok(vec)
}
/// 一个用Rust实现的Python模块。
///
/// 这个函数的名字必须与`Cargo.toml`中的`lib.name`匹配
#[pymodule]
fn python_rust2(_py: Python, module: &PyModule) -> PyResult<()> {
module.add_function(wrap_pyfunction!(sort, module)?)?;
Ok(())
}
在 python 中使用:
import python_rust2
sort = python_rust2.sort([2, 3, 7, 4, 5, 0, 2, 1])
print(sort)
# 运行结果
# [0, 1, 2, 2, 3, 4, 5, 7]
上面的代码是在传入 Python 的 list<T> 参数时,我们可以使用 Rust 的 Vec<T> 来接收并处理。
0x02 在 Python 中使用 Rust 结构体
如果我们想在 Python 中使用 Rust 中的结构体类型,那也是非常简单的。下面是在 Rust 创建了一个 Dog 的结构体,并在 Python 中使用:
use pyo3::prelude::*;
#[pyclass]
struct Dog {
#[pyo3(get, set)]
pub id: isize,
#[pyo3(get, set)]
pub name: String,
}
#[pymethods]
impl Dog {
#[new]
fn new(id: isize, name: String) -> Self {
Self {
id,
name,
}
}
fn run(&self) {
println!("{} is running!", self.name);
}
}
从上面的代码中,我们可以看到有4个标注:
#[pyclass]:如果想要自定义Python类类型,需要将#[pyclass]属性添加到 Rust 结构体上或无字段枚举(类C形式的枚举)上。#[pyo3(get, set)]:能够在Python中获取或设置结构体的字段。#[pymethods]:在impl块上使用,用于将Python中的结构体方法公开为类方法。#[new]:在构造函数上使用,这是为了能够将结构体构造为Python中的类。如果没有声明带有#[new]标记的方法,则只能从Rust创建对象实例,而不能从Python创建对象实例。
最后,我们还需要将类添加到模块中:
#[pymodule]
fn python_rust2(_py: Python, module: &PyModule) -> PyResult<()> {
module.add_class::<Dog>()?;
Ok(())
}
编写 Python 脚本并使用:
import python_rust2
dog = python_rust2.Dog(id = 1, name = "Shirley")
dog.run()
# 运行结果
# Shirley is running!
0x04 小结
本文简单介绍了下如果在 Python 中使用 Rust 的类型,如果想要了解更详细的信息,可以参阅 PyO3 的官方文档哦。