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