You need to enable JavaScript to run this app.
最新活动
大模型
产品
解决方案
定价
生态与合作
支持与服务
开发者
了解我们

如何使用PyO3将Python脚本中函数的返回值传递给Rust文件

把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

火山引擎 最新活动