从Rust的C函数中提供`char **`参数?

时间:2018-05-20 18:10:22

标签: rust

我有一个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。

任何指针?

2 个答案:

答案 0 :(得分:3)

首先,char in Rust 相当于char in C

  

char类型表示单个字符。更具体地说,由于'character'在Unicode中不是明确定义的概念,char是'Unicode scalar value',它与'Unicode code point类似但不相同}”。

在Rust中,您可以使用u8i8,具体取决于操作系统。您可以使用std::os::raw::c_char

  

相当于C的char类型。

     

C's char typeRust's char type完全不同;虽然Rust的类型表示unicode标量值,但C的char类型只是一个普通的整数。此类型将始终为i8u8,因为类型定义为一个字节长。

     

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
    };
}