戳人痛处

导航

[记]Python使用Rust编译的DLL传递字符串

前记:

  c/c艹能编译dll,现在多了选择,对 Rust;Rust编写编写dll库所需环境比c c艹确实方便许多,cargo new llib --lib即可创建一个链接库工程;

  嗯,想起visual studio那些设置,还真是让人头大;

  这里的记录为rust dll编写与python里字符串之间的传递处理:嗯 先放相关参考link:

#https://www.codenong.com/27127413/
#http://wiki.inford.net/Rust%E7%BC%96%E5%86%99DLL
#https://www.cnblogs.com/FHC1994/p/11421229.html
#https://rustcc.cn/article?id=f7505bac-1c2b-42ae-9c03-a830c6a2e6f7

 其中 ,lib.rs

use std::os::raw::c_char;
use std::ffi::{CStr, CString};

#[no_mangle]
pub extern "C" fn print_str(s: *const c_char) {
    let slice = unsafe {
        assert!(!s.is_null());
        CStr::from_ptr(s)
    };
    let r_str = slice.to_str().unwrap();
    println!("Rust side print: {:?}", r_str);
}

#[no_mangle]
pub extern "C" fn change_str(s: *mut c_char) -> *mut c_char {
    let mut string = unsafe {
        assert!(!s.is_null());
        CStr::from_ptr(s).to_string_lossy().into_owned()
    };
    string.push_str(" World!");
    println!("Rust side change: {:?}", string);
    let c_str_changed = CString::new(string).unwrap();
    c_str_changed.into_raw()
}

#[no_mangle]
pub extern "C" fn generate_str() -> *mut c_char {
    let ping = String::from("pin大g");
    println!("Rust side generate: {:?}", ping);
    let c_str_ping = CString::new(ping).unwrap();
    c_str_ping.into_raw()
}

#[no_mangle]
pub extern "C" fn free_str(s: *mut c_char) {
    unsafe {
        if s.is_null() {
            return;
        }
        CString::from_raw(s)
    };
}

dll有三种生成标准,其调用也是操作不同

这里使用cdy的标准

需在Cargo.toml里添加相关配置

[package]
name = "libtest"
version = "0.1.0"
edition = "2021"

# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html

[dependencies]

[lib]
name = "testlib" #生成dll的文件名
crate-type = ["cdylib"]

然后再在项目路径执行 Cargo build --release即可生成链接库,

编译器在生成库的时候会修改函数名,为了正常调用则需要加上

#[no_mangle]来忽略函数名修改
 
 
然后,来到python这边
from ctypes import cdll,c_char_p
#by 博客园:戳人痛处 bili:崩析

lib = cdll.LoadLibrary(r"D:\pppython\python\RustByMe\LibRealse\libtest\target\release\testlib.dll")

lib.print_str("hhhh".encode("utf-8"))
lib.generate_str.restype = c_char_p

data = lib.generate_str()

print(data.decode())

py的调用则是对应rs里的函数明进行调用;

在rs里的字符串并不符合c生成dll库的接口标准,因此会涉及到字符指针的变换;

rs默认的String是一个结构体,不是单纯的字符串数组

python到dll库的调用可以参考c生成的dll库调用;

因为是字符数组,所以有一个编码成 u8的过程;

当然 读取也是一样;

需预先声明读取的数据类型然后再做处理;

 

运行效果如下;

 

 中文字符也能很ok的传递并显示

 

->Pyo3

参考:Introduction - PyO3 user guide

pyo3是Rust对python的绑定,可以直接生成原生的python模块pyd(直接从二进制进行支持);

pip install maturin

PS D:\coded\ppyy\rspy\g1> maturin
maturin 0.12.20
Build and publish crates with pyo3, rust-cpython and cffi bindings as well as rust binaries as python packages

USAGE:
    maturin.exe <SUBCOMMAND>

OPTIONS:
    -h, --help       Print help information
    -V, --version    Print version information

SUBCOMMANDS:
    build          Build the crate into python packages
    develop        Installs the crate as module in the current virtualenv
    help           Print this message or the help of the given subcommand(s)
    init           Create a new cargo project in an existing directory
    list-python    Searches and lists the available python installations
    new            Create a new cargo project
    publish        Build and publish the crate as python packages to pypi
    sdist          Build only a source distribution (sdist) without compiling
    upload         Uploads python packages to pypi

 编写的工程可以直接以rust源码的方式打包上传pypi,当需要使用时pip安装会自动下载源码并编译;

使用指令maturin new即可生成一个rust的pyd工程;

 

PS D:\coded\ppyy\rspy\g1> maturin init
? 🤷 Which kind of bindings to use? ›
❯ pyo3
  rust-cpython
  cffi
  bin

 

 例程

use pyo3::prelude::*;

/// Formats the sum of two numbers as string.
#[pyfunction]
fn sum_as_string(a: usize, b: usize) -> PyResult<String> {
    Ok((a + b).to_string())
}

/// A Python module implemented in Rust.
#[pymodule]
fn g1(_py: Python, m: &PyModule) -> PyResult<()> {
    m.add_function(wrap_pyfunction!(sum_as_string, m)?)?;
    Ok(())
}

 编译后的wheel

 

 其中比较小的包是源码,比较大的包是直接编译的pyd模块;

可以通过rust的一些优化设置缩减编译pyd的体积;

 

 使用pip就可以安装

 

 通过py调用成功

 

 

 

---->


 

posted on 2022-04-26 09:39  戳人痛处  阅读(648)  评论(0编辑  收藏  举报