完全固定,照抄就行
Cargo.toml
[lib] crate-type = ["cdylib", "rlib"] [dependencies] pyo3 = { version = "0.27" } [features] default = [] extension-module = ["pyo3/extension-module"]pyproject.toml
[build-system] requires = ["maturin>=1.7,<2.0"] build-backend = "maturin" [tool.maturin] features = ["extension-module"]这些永远不用动。
src/lib.rs—— 唯一需要你写的部分
结构是固定的,但内容是你的。看这个 repo 的实际写法:
// [src/lib.rs#L574-L579]#[pymodule]fnrustbpe(m:&Bound<'_,PyModule>)->PyResult<()>{pyo3_log::init();m.add_class::<Tokenizer>()?;// 注册你的类Ok(())}你只需要关心两件事:
1. 函数名 = 模块名fn rustbpe(...)这里的函数名,就是 Python 里import的名字。你写fn mylib(...)就import mylib。
2. 往模块里注册你的东西
| 想暴露的东西 | 写法 |
|---|---|
| 一个类 | m.add_class::<MyStruct>()?+ struct 上加#[pyclass] |
| 一个函数 | m.add_function(wrap_pyfunction!(my_fn, m)?)?+ fn 上加#[pyfunction] |
| 一个常量 | m.add("MY_CONST", 42)? |
最小可运行示例
假设你要写一个 Python 可以调用的add(a, b)函数和一个Counter类:
usepyo3::prelude::*;#[pyfunction]fnadd(a:i64,b:i64)->i64{a+b}#[pyclass]structCounter{value:i64,}#[pymethods]implCounter{#[new]fnnew()->Self{Counter{value:0}}fnincrement(&mutself){self.value+=1;}fnget(&self)->i64{self.value}}#[pymodule]fnmylib(m:&Bound<'_,PyModule>)->PyResult<()>{m.add_function(wrap_pyfunction!(add,m)?)?;m.add_class::<Counter>()?;Ok(())}Python 端:
importmylibprint(mylib.add(1,2))# 3c=mylib.Counter()c.increment()print(c.get())# 1总结一句话
配置文件照抄,
#[pymodule]函数名改成你的模块名,然后把你的#[pyclass]/#[pyfunction]注册进去。其他的 Maturin 帮你搞定。
想了解更多 PyO3 绑定的细节和这个 repo 是怎么处理类型转换、错误的:
- PyO3 绑定架构
- 错误处理与类型转换
- GIL 管理与性能优化