rust 处理超出范围的十六进制/Unicode

vkc1a9a2  于 2023-04-06  发布在  其他
关注(0)|答案(1)|浏览(254)

我正在使用一个Rust cdylib crate,我在C++中引用和使用它。

#[no_mangle]
pub extern "C" fn some_function(name: *const c_char, text: *const c_char) {
    unsafe {
        let name = CStr::from_ptr(name).to_str().unwrap();
        let text = CStr::from_ptr(text).to_str().unwrap();

        // the rest
    }
}

当这个函数接收到字符±时,它在试图从指针中获取文本时会出现恐慌。我将这个字符作为c_str()std::string传入C++:

thread '<unnamed>' panicked at 'called `Result::unwrap()` on an `Err` value: Utf8Error { valid_up_to: 0, error_len: Some(1) }', src\lib.rs:102:50
note: run with `RUST_BACKTRACE=1` environment variable to display a backtrace

有什么方法可以在Rust中正确处理这个角色吗?我不需要以任何方式操作它,实际上这个库只是充当中间人,只需要传递它。
当我使用这个来查看我收到的字节时:

let raw = CStr::from_ptr(text);

println!("Bytes: {:?}", raw.to_bytes_with_nul());

我得到:
Bytes: [177, 0]

xzlaal3s

xzlaal3s1#

以下是我如何复制您的问题:

use std::ffi::CStr;

fn main() {
    let raw_data: &[u8] = &[177, 0];
    let raw = unsafe { CStr::from_ptr(raw_data.as_ptr().cast()) };

    println!("Bytes: {:?}", raw.to_bytes_with_nul());

    let string = raw.to_str().unwrap();
    println!("{}", string);
}
Bytes: [177, 0]
thread 'main' panicked at 'called `Result::unwrap()` on an `Err` value: Utf8Error { valid_up_to: 0, error_len: Some(1) }', src\main.rs:9:31

这里的问题是to_str()需要一个有效的UTF-8字符串。[177]不是有效的UTF-8。有效的UTF-8版本应该是:
一个二个一个一个
您的代码似乎编码不同,例如Windows-1252。我将简单地假设是这样,因为没有更多关于您的代码的知识,没有办法确定。但很有可能,因为这是西方世界Windows的默认编码。
在编码之间转换的最简单方法是通过crate encoding_rs。Rust本身只内置了UTF-8支持,所以你需要使用外部crate,这是最成熟的一种。

use std::ffi::{c_char, CStr};

use encoding_rs::WINDOWS_1252;

fn main() {
    let raw_data: *const c_char = (&[177u8, 0u8]).as_ptr().cast();

    let raw = unsafe { CStr::from_ptr(raw_data) };

    println!("Bytes: {:?}", raw.to_bytes_with_nul());

    let (string, actual_encoding, errors) = WINDOWS_1252.decode(raw.to_bytes());

    println!("String: {:?}", string);
    println!("Actual encoding: {:?}", actual_encoding);
    println!("Errors: {}", errors);
}
Bytes: [177, 0]
String: "±"
Actual encoding: Encoding { windows-1252 }
Errors: false

相关问题