如何使用PyO3将Python脚本中函数的返回值传递给Rust文件
没问题!要实现你说的需求——把Python里读取用户输入的callback函数返回值传给Rust,让Rust打印出来,这里有两种贴合场景的方案,我一步步给你讲:
方案1:Python作为主程序,调用Rust编译的动态库(推荐,适配你的GUI流程)
这个方案最符合你现有的代码逻辑:你的Python GUI已经写好了,点击按钮后直接把文本传给Rust的函数来打印。
1. 准备Rust库项目
首先创建一个Rust库项目:
cargo new --lib rust_printer cd rust_printer
然后修改Cargo.toml,配置编译为Python能调用的动态库,并添加pyo3依赖(pyo3是Rust和Python交互的核心工具):
[package] name = "rust_printer" version = "0.1.0" edition = "2021" [lib] name = "rust_printer" crate-type = ["cdylib"] # 指定编译为动态库 [dependencies] pyo3 = { version = "0.21", features = ["extension-module"] }
2. 编写Rust打印函数
在src/lib.rs里写一个接收字符串并打印的函数,同时把它暴露给Python:
use pyo3::prelude::*; // 定义能被Python调用的Rust函数,接收字符串参数 #[pyfunction] fn print_from_python(text: &str) { println!("✅ Rust收到的内容:\n{}", text); } // 把函数打包成Python模块 #[pymodule] fn rust_printer(_py: Python, m: &PyModule) -> PyResult<()> { m.add_function(wrap_pyfunction!(print_from_python, m)?)?; Ok(()) }
3. 编译Rust库
根据你的系统编译并重命名动态库,让Python能识别:
- Windows:运行
cargo build --release,把target/release/rust_printer.dll重命名为rust_printer.pyd - Linux:运行
cargo build --release,把target/release/librust_printer.so重命名为rust_printer.so - macOS:运行
cargo build --release,把target/release/librust_printer.dylib重命名为rust_printer.so
把重命名后的文件放到你的main.py同一个目录下。
4. 修改Python代码
在你的callback函数里调用Rust的打印函数,同时修正一下Tkinter文本索引的小错误(原来的0.1不对,Tkinter的Text组件索引是行.列,从1开始):
from tkinter import Tk, Text, Button # 导入编译好的Rust模块 import rust_printer root = Tk() def callback(): # 修正索引为"1.0",表示从第1行第0列开始读取到结尾 text = textEditor.get("1.0", END) # 把文本传给Rust函数打印 rust_printer.print_from_python(text) return text textEditor = Text(root, width=43, height=10) textEditor.pack() button1 = Button(root, text="Display text", command=callback) button1.pack(pady=12) root.mainloop()
现在运行main.py,输入文本点击按钮,就能看到Rust在终端里打印出内容啦!
方案2:Rust作为主程序,加载Python GUI并获取返回值
如果你想要让Rust主导流程,先启动Python的GUI,等用户操作后再获取文本打印,可以用这个方案:
1. 准备Rust项目
创建一个Rust二进制项目:
cargo new rust_call_python cd rust_call_python
修改Cargo.toml添加pyo3依赖:
[package] name = "rust_call_python" version = "0.1.0" edition = "2021" [dependencies] pyo3 = { version = "0.21", features = ["auto-initialize"] }
2. 修改Python代码
给main.py添加全局变量存储文本,以及单独的GUI运行函数:
from tkinter import Tk, Text, Button # 全局变量存储用户输入的文本 saved_text = "" root = Tk() def callback(): global saved_text saved_text = textEditor.get("1.0", END) return saved_text textEditor = Text(root, width=43, height=10) textEditor.pack() button1 = Button(root, text="Display text", command=callback) button1.pack(pady=12) def run_gui(): # 单独封装GUI事件循环 root.mainloop()
3. 编写Rust主程序
在src/main.rs里初始化Python环境,加载main.py,运行GUI后获取文本:
use pyo3::prelude::*; fn main() -> PyResult<()> { // 获取Python全局解释器锁,初始化环境 let py = Python::acquire_gil().python(); // 把当前目录添加到Python路径,确保能导入main.py let sys = py.import("sys")?; let path = sys.getattr("path")?; path.call_method1("append", (".",))?; // 导入我们的Python模块 let main_module = py.import("main")?; println!("请在弹出的Python窗口中输入文本,点击按钮后关闭窗口..."); // 运行Python的GUI事件循环 main_module.call0("run_gui")?; // 从Python全局变量中读取文本并打印 let saved_text = main_module.getattr("saved_text")?.extract::<String>()?; println!("🎉 Rust获取到的Python输入内容:\n{}", saved_text); Ok(()) }
4. 运行Rust程序
把main.py放到Rust项目根目录,运行cargo run,弹出GUI窗口操作后,关闭窗口就能看到Rust打印的内容了。
内容的提问来源于stack exchange,提问作者Nick M




