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

时间:2019-06-28 09:02:23

标签: python python-3.x rust pyo3

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

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

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

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

执行我的python脚本的锈迹代码:

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)
}

我想从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 !");
}

我的python脚本:

hello_from_rust()

我得到这个输出:

RUNNING :
[
hello_from_rust()
]
Error: PyErr { type: Py(0x7f9cdd1e9580, PhantomData) }

1 个答案:

答案 0 :(得分:5)

如果我正确理解了您的问题,那么您要执行的操作涉及三个步骤:

  1. 创建一个包含函数const BundleTracker = require("webpack-bundle-tracker"); module.exports = { // on Windows you might want to set publicPath: "http://127.0.0.1:8080/" publicPath: "http://localhost:8080/", outputDir: './dist/', chainWebpack: config => { // const svgRule = config.module.rule('svg') // svgRule.uses.clear() // // add replacement loader(s) // svgRule // .use('vue-svg-loader') // .loader('vue-svg-loader') config .plugin('BundleTracker') .use(BundleTracker, [{filename: './webpack-stats.json'}]) config.output .filename('bundle.js') config.optimization .splitChunks(false) config.resolve.alias .set('__STATIC__', 'static') .set('__MEDIA__', 'media') config.devServer // the first 3 lines of the following code have been added to the configuration .public('http://localhost:8080') .host('127.0.0.1') .port(8080) .hotOnly(true) .watchOptions({poll: 1000}) .https(false) .disableHostCheck(true) .headers({"Access-Control-Allow-Origin": ["\*"]}) },}; 的Python模块
  2. 在Python脚本svg中使用它
  3. 从Rust中运行hello_from_rust()

我无法完全重现您的问题,但看来问题的根源可能在于第一步或第二步。

使用PyO3定义Python模块

PyO3 documentation开始,我希望deep_hello.py位于Rust文件中,该文件定义了一个类似于以下内容的Python模块:

deep_hello.py

您可以使用Cargo将其构建到Python模块中(请参见here;说明因您的操作系统而略有不同),然后放置生成的hello_from_rust()(Linux或MacOS)或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(()) } (Windows)文件与Python脚本位于同一目录中。

注意

您必须按照.so的方式创建函数来初始化Python模块。如果不这样做,您的Rust库可能仍会编译,但是您将无法导入.pyd

使用新的Python模块

您的hello_module脚本应如下所示:

hello_from_rust

确保deep_hello.pyimport hello_module hello_module.hello_from_rust() 文件可在您的.so中访问(例如,将其放置在与脚本相同的目录中),并使用Python运行.pyd > = 3.5应该可以。 (请注意,您的系统Python可能是Python 2,因此您可能要使用新版本的Python创建一个Anaconda环境并在其中运行。)

对我来说,按照以下步骤操作即可。

PYTHON_PATH

注意

确保您记得在Python脚本中deep_hello.py!您的(ruspy) ruspy $ python deep_hello.py Hello from rust from python ! 返回的import hello_module让我想知道问题是否出在您的Python脚本中,确实,我希望PyErr没有前面的py.run(&script, None, None)会产生一个{{ 1}},即使您正确组合了hello_from_rust()模块。

从Rust从Python调用Rust

我不确定您为什么要这样做,但是现在您应该可以从Rust运行from deep_hello import *