基于 Rust 编写 Python 拓展

454 阅读2分钟

小知识,大挑战!本文正在参与“程序员必备小知识”创作活动。

本文已参与 「掘力星计划」 ,赢取创作大礼包,挑战创作激励金

图片

这篇文章目前用的所有rust相关的包必须是最新的。环境基于mac

安装rust

关于rust的安装我就不,我将会放在公众号的次条。成功之后我们继续下面步骤

Rust 发布的工具链包括了 stable、beta 和 nightly 三种不同版本。nightly 是最激进的版本,包含了大量(可能不稳定)的新/高级特性。stable 版本目前可能还不支持一些高级特性。beta 介于两者之间。这里我们需要使用最新的nightly版本。

安装nightly版本

rustup install nightly

如果安装过就更新

rustup update nightly

切换到nightly

rustup default nightly

nightly版本查看

rustc 1.41.0-nightly (412f43ac5 2019-11-24)

文件配置

在文件夹.cargo创建config文件

cd ~/.cargo
touch config
subl config

输入下面内容

[target.x86_64-apple-darwin]
rustflags = [
  "-C""link-arg=-undefined",
  "-C""link-arg=dynamic_lookup",
]

如果不配置会报一个c语言的错误,加上就完事了。

创建项目

cargo +nightly new pyo3demo

执行上面的命令之后会创建一个pyo3demo文件夹,该文件夹里包含一个Cargo.toml配置文件和src文件夹。

所有要用cargo管理的必须有Cargo.toml文件,而且必须是这个名字,而且首字母必须大写。

Cargo.toml内容如下

[package]
name = "r2p"
version = "0.1.0"
edition = "2018"

[lib]
name = "r2p"
crate-type = ["cdylib"]

[dependencies.pyo3]
version = "0.8.3"
features = ["extension-module"]

然后src文件下面创建lib.rs。内容如下:

use pyo3::prelude::*;
use std::f64::consts::PI;
use pyo3::wrap_pyfunction;

#[pyfunction]
fn hello() -> PyResult<()> {
    println!("公众号:Python学习开发");
    Ok(())
}

#[pyfunction]
fn pi_times( n: usize ) -> PyResult<Vec<f64>> {
    Ok(
        (0..n).map(|i| i as f64 * PI).collect()
    )
}

#[pymodule]
fn r2p(_py: Python, m: &PyModule) -> PyResult<()> {
    m.add_wrapped(wrap_pyfunction!( hello ))?;
    m.add_wrapped(wrap_pyfunction!( pi_times ))?;

    Ok(())
}

这里使用的是rust的一个pyo3模块。按照上面的步骤进行就好了。

编译项目

返回项目的根目录,然后执行下面命令

cargo +nightly build --release

如果执行成功,会生成一个target文件夹,进入target还有个release文件。
发现文件libr2p.dylib,将其拷贝到项目根目录,然后重命名为r2p.so。
到目前为止rust这边的工作就都做完了。

下面是python这边的

打开python3

import r2p
r2p.hello()

得到结果如下\

图片


恭喜你成功了,使用rust写python拓展目前还不算成熟,就是当个玩具的,关于C对Python拓展可以看我之前的文章