我对生锈很陌生。如何从可以在Python中使用的Rust函数返回String
?在
以下是我的Rust实现:
use std::ffi::CString;
#[no_mangle]
pub extern fn query() -> CString {
let s = CString::new("Hello!").unwrap();
return s;
}
以及调用它的Python代码:
^{pr2}$我得到了一个分割错误时,它运行。
编辑:使用Vladimir Matveev下面的Rust代码,我可以让它与我的python代码的更改一起工作:
from ctypes import *
lib = cdll.LoadLibrary("target/release/libtest.so")
lib.query.restype = c_char_p
result = lib.query()
print cast(result, c_char_p).value
lib.free_query(result)
最直接的说法是:
这里我们返回一个指向} 方法就是这样做的——它按值使用
char
s的以零结尾的序列的指针,该序列可以传递给Python的c_char_p
。你不能仅仅返回CString
,因为它是Rust结构,不应该直接在C代码中使用——它包装了Vec<u8>
,实际上由三个指针大小的整数组成。它与C的char*
不直接兼容。我们需要从中得到一个原始指针。^{CString
,“忽略”它,这样它的分配就不会被破坏,并返回一个指向数组开头的*mut c_char
指针。在然而,这样的话,字符串就会被泄露,因为我们忘记了它在锈边的分配,它永远也不会被释放。我不太了解Python的FFI,但是解决这个问题最直接的方法是创建两个函数,一个用于生成数据,另一个用于释放数据。然后需要通过调用以下释放函数从Python端释放数据:
^{pr2}$^{} 方法接受一个
*mut c_char
指针并从中创建一个CString
实例,计算进程中底层以零结尾的字符串的长度。此操作意味着所有权转移,因此结果CString
值将拥有分配,当它被删除时,分配将被释放。这正是我们想要的。在这里的问题是您直接返回一个
CString
,它与C
中的字符串表示不对应(您可以看到here的源代码CString
)。在应该使用
s.as_ptr()
返回指向字符串的指针。但是,您需要确保在函数末尾没有释放字符串,因为这将导致指针悬空。在我能想到的唯一解决方案是使用
forget
让rust忘记变量,而不是释放它。当然,您需要在以后找到释放字符串的方法,以避免内存泄漏(参见Vladimir的答案)。在根据我提到的更改,您的Rust代码应该是以下内容:
相关问题 更多 >
编程相关推荐