python中调用rust程序概述
概述
使用rust-cpython将rust程序做为python模块调用;
通常为了提高python的性能;
参考-github
https://github.com/dgrunwald/rust-cpython
环境
系统:本次示例为centos7
python:python3
rust未安装时安装
curl https://sh.rustup.rs -sSf | sh source "$HOME/.cargo/env"
创建 rust lib库项目
cargo new rust2py --lib 或者使用IDE创建一个rust lib库项目
cat Cargo.toml
[package] name = "rust2py" version = "0.1.0" edition = "2021" # See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html [lib] name = "rust2py" crate-type = ["cdylib"] [dependencies.cpython] version = "^0.7" features = ["extension-module"]
lib.rs
#[cfg(test)]
mod tests {
#[test]
fn it_works() {
assert_eq!(2 + 2, 4);
}
}
#[macro_use]
extern crate cpython;
use cpython::{PyResult, Python, py_module_initializer, py_fn};
pub fn print_str(a: String) -> String {
print!("{:#?}",a);
a
}
pub fn print_str_py(_: Python, a: String) -> PyResult{
let mm = print_str(a);
Ok(mm)
}
// logic implemented as a normal rust function
fn sum_as_str(a:i64, b:i64) -> String {
format!("{}", a + b).to_string()
}
// rust-cpython aware function. All of our python interface could be
// declared in a separate module.
// Note that the py_fn!() macro automatically converts the arguments from
// Python objects to Rust values; and the Rust return value back into a Python object.
fn sum_as_str_py(_: Python, a:i64, b:i64) -> PyResult {
let out = sum_as_str(a, b);
Ok(out)
}
py_module_initializer!(rust2py, init_rust2py, PyInit_rust2py, |py, m| {
m.add(py, "__doc__", "This module is implemented in Rust.")?;
m.add(py, "print_str", py_fn!(py, print_str_py(a: String)))?;
m.add(py, "sum_as_str", py_fn!(py, sum_as_str_py(a: i64, b:i64)))?;
Ok(())
});
注意: py_module_initializer方法的参数的中rust2py一定要与模块的名称一致,这个不是随便写的字符串名称, 比如PyInit_rust2py就表示将来在python中调用的模块名称是rust2py
编译并复制到python的模块
cargo build --release cd target/release/ cp librust2py.so /ai/app/anaconda3/lib/python3.9/site-packages/rust2py.so 注意:复制到python模块的so没有lib前缀
import rust2py rust2py.sum_as_str(2,5)
cargo new alg 准备C文件
cd alg
创建一个cc目录,放c文件,cc计划作为c语言在rust中的模块名称
xt@kl:/wks/rust/alg$ mkdir -p source/cc
xt@kl:/wks/rust/alg$ cd source/cc/
xt@kl:/wks/rust/alg/source/cc$ vim linear.c
int double_input(int input) {
return input * 2;
}
Cargo.toml
[package]
name = "alg"
version = "0.1.0"
edition = "2021"
[dependencies]
libc = "0.2"
[build-dependencies]
cc = "1.0"
rust调用C方法
xt@kl:/wks/rust/alg/source/cc$ cd ../..
xt@kl:/wks/rust/alg$ cd src/
xt@kl:/wks/rust/alg/src$ mkdir call_cc
xt@kl:/wks/rust/alg/src$ echo "pub mod cc;" > call_cc/mod.rs
xt@kl:/wks/rust/alg/src$ cd call_cc/
xt@kl:/wks/rust/alg/src/call_cc$ ls
mod.rs
xt@kl:/wks/rust/alg/src/call_cc$ vim cc.rs
#![allow(unused)]
extern crate libc;
extern {
fn double_input(input: libc::c_int) -> libc::c_int;
}
pub fn test() {
let input = 4;
let output = unsafe { double_input(input) };
println!("{} * 2 = {}", input, output);
}
xt@kl:/wks/rust/alg/src/call_cc$ cd ../..
xt@kl:/wks/rust/alg$ vim build.rs
extern crate cc;
fn main() {
cc::Build::new()
.file("source/cc/linear.c")
.compile("liblinear.a");
}
main.rs
|
|
|
|
|
|
|
|
https://docs.rs/pyo3/latest/pyo3/
cd rtp python -m venv .env source .env/bin/activate pip install maturin maturin develop # lots of progress output as maturin runs the compilation... $ python >>> import string_sum >>> string_sum.sum_as_string(5, 20) '25'
|
|
|
|
|
|
|
|