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