[记]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的传递并显示