rust-cpython概述

python中调用rust程序概述

 
概述
使用rust-cpython将rust程序做为python模块调用;
通常为了提高python的性能;

    
参考-github
https://github.com/dgrunwald/rust-cpython

    
环境
系统:本次示例为centos7

python:python3

rust lib项目创建

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)

rust调用C

 
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

 

    

 

    

 

    

 


 

  

 


参考