最直接的版本是这样的:
use libc::c_char;use std::ffi::CString;use std::mem;#[no_mangle]pub extern fn query() -> *mut c_char { let s = CString::new("Hello!").unwrap(); s.into_raw()}在这里,我们返回一个指向
chars的零终止序列的指针,该序列可以传递给Python的
c_char_p。您不能仅仅
CString因为它是Rust结构而不应该直接在C代码中使用而返回-
它包装
Vec<u8>并实际上由三个指针大小的整数组成。它与C
char*直接不兼容。我们需要从中获取原始指针。
CString::into_raw()方法做到这一点-
它使用
CStringby值,“忘记”它,这样它的分配不会被破坏,并返回一个
*mut c_char指向数组开头的指针。
但是,这种方式会泄漏字符串,因为我们忘记了它在Rust端的分配,并且永远也不会释放它。我对Python的FFI不够了解,但是解决此问题的最直接方法是创建两个函数,一个用于生成数据,另一个用于释放数据。然后,您需要通过调用以下释放函数来从Python端释放数据:
// above function#[no_mangle]pub extern fn query() -> *mut c_char { ... }#[no_mangle]pub extern fn free_query(c: *mut c_char) { // convert the pointer back to `CString` // it will be automatically dropped immediately unsafe { CString::from_raw(c); }}CString::from_raw()方法接受一个
*mutc_char指针并从中创建一个
CString实例,以计算该过程中基础的零终止字符串的长度。此操作意味着所有权转移,因此结果
CString值将拥有分配,并且在删除分配值后将释放分配。这正是我们想要的。



