如何使用pyo3从Python文件调用rust函数?

Sur*_*aii 5 python rust python-3.x pyo3

我正在开发一个视频游戏,在该游戏中,我需要从python文件中设置生锈的objets(例如,添加一个带有texture:“” coords:“” text:“” action:“”)的按钮。

我正在使用pyo3板条箱链接python和rust。

我成功地从我的rust代码调用了python脚本。

但是我找不到如何从python文件调用rust函数。

执行我的python脚本的Rust代码:

fn main() -> PyResult<()> {
    let gil = Python::acquire_gil();
    let py = gil.python();
    let script = fs::read_to_string("deep_hello.py")?;

    println!("RUNNING :\n[\n{}]", script);
    py.run(&script, None, None)
}
Run Code Online (Sandbox Code Playgroud)

我想从python脚本调用的Rust函数:

/// hello_from_rust(/)
/// --
///
/// This function prints hello because she is very nice.
#[pyfunction]
fn hello_from_rust() {
    println!("Hello from rust from python !");
}
Run Code Online (Sandbox Code Playgroud)

我的python脚本:

hello_from_rust()
Run Code Online (Sandbox Code Playgroud)

我得到这个输出:

RUNNING :
[
hello_from_rust()
]
Error: PyErr { type: Py(0x7f9cdd1e9580, PhantomData) }
Run Code Online (Sandbox Code Playgroud)

Eme*_*kin 5

如果我正确理解了您的问题,那么您尝试执行的操作包括三个步骤:

  1. 创建一个包含该函数的 Python 模块 hello_from_rust()
  2. 在 Python 脚本中使用它 deep_hello.py
  3. deep_hello.py从 Rust 中运行。

我无法完全重现您的问题,但问题的根源似乎在第一步或第二步。

使用 PyO3 定义 Python 模块

PyO3 文档中,我希望hello_from_rust()在 Rust 文件中定义一个看起来像这样的 Python 模块:

use pyo3::prelude::*;
use pyo3::wrap_pyfunction;

#[pyfunction]
fn hello_from_rust() {
    println!("Hello from rust from python !");
}

#[pymodule]
fn hello_module(py: Python, m: &PyModule) -> PyResult<()> {
    m.add_wrapped(wrap_pyfunction!(hello_from_rust));

    Ok(())
}
Run Code Online (Sandbox Code Playgroud)

您可以使用 Cargo 将其构建到 Python 模块中(请参阅此处;根据您的操作系统,说明略有不同)并将生成的.so(Linux 或 MacOS)或.pyd(Windows)文件与您的 Python 脚本放在同一目录中。

笔记

您必须创建一个类似于hello_module初始化 Python 模块的函数。如果不这样做,您的 Rust 库可能仍会编译,但您将无法导入hello_from_rust.

使用你的新 Python 模块

您的deep_hello.py脚本应如下所示:

import hello_module
hello_module.hello_from_rust()
Run Code Online (Sandbox Code Playgroud)

确保.soor.pyd文件可在您的PYTHON_PATH(例如,将其与您的脚本放在同一目录中),deep_hello.py使用 Python >= 3.5运行应该可以工作。(请注意,您的系统 Python 可能是 Python 2,因此您可能希望使用较新版本的 Python 创建一个 Anaconda 环境并在其中工作。)

对我来说,遵循这些步骤就成功了。

(ruspy) ruspy $ python deep_hello.py
Hello from rust from python !
Run Code Online (Sandbox Code Playgroud)

笔记

确保你记得import hello_module在你的 Python 脚本中!PyErr你的返回py.run(&script, None, None)让我想知道问题是否真的出在你的 Python 脚本中,事实上,即使你正确地组合了你的模块,我也希望hello_from_rust()没有前面from deep_hello import *的产生 a 。NameErrordeep_hello

从 Rust 从 Python 调用 Rust

我不完全确定您为什么要这样做,但是您现在应该可以deep_hello.py从 Rust运行。