原理:
将rust源码编译为一个python lib库 ,在python中调用这个lib库。
步骤:
使用 PyO3
创建 Python 扩展模块
PyO3
是一个非常流行的库,允许你将 Rust 代码编译为 Python 扩展模块,并在 Python 中直接调用它。
安装maturin
python
pip install maturin
创建 Rust 项目
- 在rust 项目中创建lib.rs文件
在rust 中,lib.rs 默认编译为库,而main.rs默认编译为可执行文件
- 编辑lib.rs文件
rust
use pyo3::prelude::*;
use pyo3::wrap_pyfunction;
#[pyfunction]
fn add_measurement_signal(
a2l_info: &mut A2lFileInfo,
measurement_info: &MeasurementInfo,
) -> PyResult<()> {
a2l_info.add_measurements.push(measurement_info.clone());
Ok(())
}
#[pyfunction]
fn deleted_measurements_signal(
a2l_info: &mut A2lFileInfo,
measurement_info: &MeasurementInfo,
) -> PyResult<()> {
a2l_info.delete_measurements.push(measurement_info.clone());
Ok(())
}
#[pyclass]
#[derive(Debug, Clone, PartialEq, Eq)]
pub struct MeasurementData {
#[pyo3(get, set)]
pub name: String,
#[pyo3(get, set)]
pub data_type: String,
#[pyo3(get, set)]
pub address: u64,
#[pyo3(get, set)]
pub byte_size: u32,
}
#[pymethods]
impl MeasurementData {
#[new]
fn new(name: String, data_type: String, address: u64, byte_size: u32) -> Self {
MeasurementData {
name,
data_type,
address,
byte_size,
}
}
// 显式实现 copy 方法来进行深拷贝
fn copy(&self) -> MeasurementData {
self.clone() // 调用 Clone trait 进行深拷贝
}
}
#[pyclass]
#[derive(Debug, Clone, PartialEq, Eq)]
pub struct MeasurementInfo {
#[pyo3(get, set)]
pub module_name: String,
#[pyo3(get, set)]
pub group_name: String,
#[pyo3(get, set)]
pub measurement_data: MeasurementData,
}
#[pymethods]
impl MeasurementInfo {
#[new]
fn new(module_name: String, group_name: String, measurement_data: MeasurementData) -> Self {
MeasurementInfo {
module_name,
group_name,
measurement_data,
}
}
// 显式实现 copy 方法来进行深拷贝
fn copy(&self) -> MeasurementInfo {
self.clone() // 调用 Clone trait 进行深拷贝
}
}
#[pyclass]
#[derive(Debug, Clone, PartialEq, Eq)]
struct A2lFileInfo {
#[pyo3(get, set)]
pub file_name: String,
#[pyo3(get, set)]
pub project_name: String,
#[pyo3(get, set)]
pub modules: Vec<String>,
#[pyo3(get, set)]
pub groups: Vec<String>,
#[pyo3(get, set)]
pub delete_measurements: Vec<MeasurementInfo>,
#[pyo3(get, set)]
pub add_measurements: Vec<MeasurementInfo>,
}
#[pymethods]
impl A2lFileInfo {
#[new]
fn new(
file_name: String,
project_name: String,
modules: Vec<String>,
groups: Vec<String>,
read_measurements: Vec<MeasurementInfo>,
delete_measurements: Vec<MeasurementInfo>,
add_measurements: Vec<MeasurementInfo>,
) -> Self {
A2lFileInfo {
file_name,
project_name,
modules,
groups,
read_measurements,
delete_measurements,
add_measurements,
}
}
// 显式实现 copy 方法来进行深拷贝
fn copy(&self) -> A2lFileInfo {
self.clone() // 调用 Clone trait 进行深拷贝
}
}
#[pymodule]
fn a2l_edit_lib(_py: Python, m: &PyModule) -> PyResult<()> {
m.add_function(wrap_pyfunction!(add_measurement_signal, m)?)?;
m.add_function(wrap_pyfunction!(deleted_measurements_signal, m)?)?;
m.add_class::<A2lFileInfo>()?;
m.add_class::<MeasurementInfo>()?;
m.add_class::<MeasurementData>()?;
Ok(())
}
对于内部结构体,需要将成员变量设置pub 并添加修饰符:
rust
#[pyo3(get, set)]
pub name: String,
- 配置Cargo.toml
rust
[package]
name = "xxxx_lib"
version = "0.1.0"
edition = "2021"
[lib]
crate-type = ["cdylib"] # 编译为动态链接库
# 在 [dependencies] 部分添加
[dependencies]
pyo3 = { version = "0.21.0", features = ["extension-module"] }
[workspace]
resolver = "2"
[patch.crates-io]
- 编译rust lib
rust
cargo check
maturin build
在target/wheels 目录下生成lib 安装文件
- 安装lib库
bash
pip install --force-reinstall xxx_lib-0.1.0-cp310-cp310-manylinux_2_34_x86_64.whl
在python 源码中调用rust lib
python
import xxx_lib
# 创建 MeasurementData 和 MeasurementInfo
data = a2l_edit_lib.MeasurementData(signal.name, signal.type_name, address, byte_size)
data_info = a2l_edit_lib.MeasurementInfo(module_name, group_name, data.copy())
a2l_edit_lib.add_measurement_signal(self.a2l_parser_info, data_info)
a2l_edit_lib.deleted_measurements_signal(self.a2l_parser_info, data_info)
可以直接使用对外导出的结构体对象,在测试中发现,可以读取A2lFileInfo 对象,但是没办法修改内部值,只能通过增加rust 接口函数来实现对A2lFileInfo 对象的修改。