我用rust来调用c++,有bindgencc生成的 struct . struct 字段类型类似于[i8;11][i8;n].我想要设置这些字段. 如何编写一个通用函数将RUST String/CStr/CString转换为i8/c_char数组?

推荐答案

您必须了解两个问题:

  • 空终止:RUST字符串不是空终止的,C/C++字符串是空终止的.
  • 编码:RUST字符串为UTF-8编码,C/C++字符串编码取决于操作系统.在大多数系统上,C/C++字符串也是UTF-8,但在Windows上,它很可能是其他字符串,如Windows-1252.在这种情况下,您需要一个像encoding_rs这样的外部库来正确转换编码.

让我们假设C/C++字符串也是用UTF-8编码的(同样,这也是您可以在Windows上not做的假设).然后,您可以(例如)将其转换为:

use std::ffi::CString;

fn main() {
    // Fill with dummy data to 'simulate' the situation of uninitialized memory
    let mut c_array = [42i8; 11];

    // The data that should get written into c_array
    let rust_string = String::from("Hello!");

    // Convert to CString, required for FFI
    let rust_cstring = CString::new(rust_string).unwrap();
    // Extract null-terminated raw data
    let byteslice = rust_cstring.as_bytes_with_nul();

    // Write data. Note that this will panic if `byteslice` is longer than `c_array`.
    let mut byteslice_iter_i8 = byteslice.iter().map(|v| *v as i8);
    c_array[0..byteslice.len()].fill_with(|| byteslice_iter_i8.next().unwrap());

    println!("{:?}", c_array);
}
[72, 101, 108, 108, 111, 33, 0, 42, 42, 42, 42]

当然,还有其他方法,这一种方法可能不是实现这一点的唯一最佳方法,但我希望它能够演示基本原则.

Rust相关问答推荐

在rust中如何修改一个盒装函数并将其赋回?

Rust TcpStream不能在读取后写入,但可以在不读取的情况下写入.为什么?

在Rust中显式装箱受生存期限制的转换闭包

从Type::new()调用函数

自定义结果枚举如何支持`?`/`FromResidual`?

无法定义名为&new&的关联函数,该函数的第一个参数不是self

有没有一种惯用的方法来判断VEC中是否存在变体?

在生存期内将非静态可变引用转换为范围内的静态可变引用

Rust移动/复制涉及实际复制时进行检测

在 Rust 中用问号传播错误时对类型转换的困惑?

没有明确地说return会产生错误:match arms have incompatible types

rust tokio::spawn 在 mutexguard 之后等待

如何获取函数中borrow 的切片的第一部分?

Rust 函数指针似乎被borrow 判断器视为有状态的

判断对象是 PyDatetime 还是 Pydate 的实例?

预期的整数,找到 `&{integer}`

使用方法、关联函数和自由函数在 Rust 中初始化函数指针之间的区别

Rust HRTB 是相同的,但编译器说一种类型比另一种更通用

如何为枚举中的单个或多个值返回迭代器

将数据序列化为 struct 模型,其中两个字段的数据是根据 struct 中的其他字段计算的