pyo3 官方使用手册: 【点击查看】
maturin 构建使用工具: 【点击查看】
一、前言
安装 pip install maturin
主要有以下三个命令:
-
maturin publish
将 crate 构建到 python 包中并将它们发布到 pypi。 -
maturin build
构建轮子并将它们存储在一个文件夹中(target/wheels默认情况下),但不上传它们。可以使用twine上传那些。 -
maturin develop
构建 crate 并将其作为 python 模块直接安装在当前 virtualenv 中。请注意,虽然maturin develop速度更快,但它并不支持运行pip install后maturin build支持的所有功能。
pyo3并rust-cpython自动检测绑定,对于 cffi 或二进制文件,您需要通过-b cffi或-b bin. maturin 不需要额外的配置文件,也不会与现有的 setuptools-rust 或 Milksnake 配置冲突。您甚至可以将其与测试工具(例如tox )集成。test-crates文件夹中有不同绑定的示例。包的名称将是货物项目的名称,即在名称字段[package]的部分Cargo.toml。导入时使用的模块名称将是name该[lib]部分中的值(默认为包的名称)。对于二进制文件,它只是由货物生成的二进制文件的名称。
1.1 官方示例
Cargo.tmol
[lib]
name = "string_sum"
crate-type = ["cdylib"]
[dependencies.pyo3]
version = "0.13.2"
features = ["extension-module"]
lib.rs
use pyo3::prelude::*;
use pyo3::wrap_pyfunction;
/// Formats the sum of two numbers as string.
#[pyfunction]
fn sum_as_string(a: usize, b: usize) -> PyResult<String> {
Ok((a + b).to_string())
}
/// A Python module implemented in Rust.
#[pymodule]
fn string_sum(_py: Python, m: &PyModule) -> PyResult<()> {
m.add_function(wrap_pyfunction!(sum_as_string, m)?)?;
Ok(())
}
生成 whl 文件
执行开发编译 maturin build --interpreter python
执行发布编译 maturin build --release --interpreter python
安装并测试
cd target\wheels
pip install string_sum-0.1.0-cp37-none-win_amd64.whl
二、Rust 与 Python 的ndarray交互
编写 Python 拓展 Whl文件。
rust ndarray 【基础使用】
rust-numpy 【pyO3 项目地址】 ,使用文档:rust-numpy , rust-ndarray
[lib]
name = "rust_ext"
crate-type = ["cdylib"]
[dependencies]
pyo3 = { version = "0.21", features = ["extension-module"] }
numpy = "0.21"
use numpy::ndarray::{ArrayD, ArrayViewD, ArrayViewMutD};
use numpy::{IntoPyArray, PyArrayDyn, PyReadonlyArrayDyn, PyArrayMethods};
use pyo3::{pymodule, types::PyModule, PyResult, Python, Bound};
#[pymodule]
fn rust_ext<'py>(_py: Python<'py>, m: &Bound<'py, PyModule>) -> PyResult<()> {
// example using immutable borrows producing a new array
fn axpy(a: f64, x: ArrayViewD<'_, f64>, y: ArrayViewD<'_, f64>) -> ArrayD<f64> {
a * &x + &y
}
// example using a mutable borrow to modify an array in-place
fn mult(a: f64, mut x: ArrayViewMutD<'_, f64>) {
x *= a;
}
// wrapper of `axpy`
#[pyfn(m)]
#[pyo3(name = "axpy")]
fn axpy_py<'py>(
py: Python<'py>,
a: f64,
x: PyReadonlyArrayDyn<'py, f64>,
y: PyReadonlyArrayDyn<'py, f64>,
) -> Bound<'py, PyArrayDyn<f64>> {
let x = x.as_array();
let y = y.as_array();
let z = axpy(a, x, y);
z.into_pyarray_bound(py)
}
// wrapper of `mult`
#[pyfn(m)]
#[pyo3(name = "mult")]
fn mult_py<'py>(a: f64, x: &Bound<'py, PyArrayDyn<f64>>) {
let x = unsafe { x.as_array_mut() };
mult(a, x);
}
Ok(())
}
[package]
name = "numpy-test"
[dependencies]
pyo3 = { version = "0.21", features = ["auto-initialize"] }
numpy = "0.21"
use numpy::{PyArray1, PyArrayMethods};
use pyo3::{types::{IntoPyDict, PyAnyMethods}, PyResult, Python};
fn main() -> PyResult<()> {
Python::with_gil(|py| {
let np = py.import_bound("numpy")?;
let locals = [("np", np)].into_py_dict_bound(py);
let pyarray = py
.eval_bound("np.absolute(np.array([-1, -2, -3], dtype='int32'))", Some(&locals), None)?
.downcast_into::<PyArray1<i32>>()?;
let readonly = pyarray.readonly();
let slice = readonly.as_slice()?;
assert_eq!(slice, &[1, 2, 3]);
Ok(())
})
}
Cargo 工具文档
https://doc.rust-lang.org/cargo/reference/manifest.html
https://doc.rust-lang.org/stable/cargo/
其它参考
https://blog.csdn.net/wangmarkqi/article/details/104618641
https://blog.csdn.net/muzico425/article/details/103331676