我有一个C函数(简化)看起来像这样:
static char buffer[13];
void get_string(const char **s) {
sprintf(buffer, "Hello World!");
*s = buffer;
}
我在Rust中声明了它:
extern pub fn get_string(s: *mut *const c_char);
但我无法弄清楚调用它所需的咒语,并将结果转换为Rust字符串。我尝试的所有内容都无法编译,或导致SEGV。
任何指针?
答案 0 :(得分:3)
首先,char
in Rust 不相当于char
in C:
char
类型表示单个字符。更具体地说,由于'character'在Unicode中不是明确定义的概念,char
是'Unicode scalar value',它与'Unicode code point类似但不相同}”。
在Rust中,您可以使用u8
或i8
,具体取决于操作系统。您可以使用std::os::raw::c_char
:
相当于C的
char
类型。C's
char
type与Rust'schar
type完全不同;虽然Rust的类型表示unicode标量值,但C的char
类型只是一个普通的整数。此类型将始终为i8
或u8
,因为类型定义为一个字节长。C字符最常用于制作C字符串。与Rust不同,字符串的长度包含在字符串旁边,C字符串用字符
'\0'
标记字符串的结尾。有关详细信息,请参阅CStr
。
首先,我们需要一个可以传递给函数的变量:
let mut ptr: *const c_char = std::mem::uninitialized();
要将其作为*mut
传递,您只需使用参考:
get_string(&mut ptr);
现在使用*const c_char
创建CStr
:
let c_str = CStr::from_ptr(ptr);
要将其转换为String
,您可以选择:
c_str.to_string_lossy().to_string()
或
c_str().to_str().unwrap().to_string()
但是,如果您不需要,则不应使用String
。在大多数情况下,Cow<str>
满足需求。可以使用c_str.to_string_lossy()
:
如果
CStr
的内容是有效的UTF-8数据,则此函数将返回带有相应Cow::Borrowed([&str])
切片的[&str]
。否则,它将使用U+FFFD REPLACEMENT CHARACTER
替换任何无效的UTF-8序列,并返回Cow::[Owned](String)
的结果。
您可以在Playground上看到这一点。 This Playground显示to_string_lossy()
的使用情况。
答案 1 :(得分:0)
结合Passing a Rust variable to a C function that expects to be able to modify it
unsafe {
let mut c_buf = std::ptr::null();
get_string(&mut c_buf);
}
使用How do I convert a C string into a Rust string and back via FFI?:
extern crate libc;
use libc::c_char;
use std::ffi::CStr;
use std::str;
extern "C" {
fn get_string(s: *mut *const c_char);
}
fn main() {
unsafe {
let mut c_buf = std::ptr::null();
get_string(&mut c_buf);
let c_str = CStr::from_ptr(c_buf);
let str_slice: &str = c_str.to_str().unwrap();
let str_buf: String = str_slice.to_owned(); // if necessary
};
}