我在 Windows 上有一个 std::ffi::OsString,但我需要将 std::ffi::CString 传递给 FFI 函数。有没有办法将 OsString 转换为 CString

我知道在 Windows 上,OsString 由 WTF-8 编码的缓冲区支持。基本上所有需要发生的是附加一个 ASCII nul 字符并从中创建一个 CString 。有没有好的方法可以做到这一点?如果没有,是否可以直接访问该缓冲区?

下面是一些示例代码:

extern "system" fn some_ffi(s: *mut c_char);

fn my_func(os_string: &OsString) {
    let c_string: CString = // ???

    some_ffi(c_string.as_raw())
}

最佳答案

在类 Unix 系统上,您可以通过 OsStr 获取 OsString&[u8] 的原始字节作为 std::os::unix::ffi::OsStrExt::as_bytes 。您可以将该切片直接传递给 CString::new

在 Windows 上,您无法获取 OsStrOsString 的原始字节。 WTF-8 编码被视为私有(private)实现细节。唯一的保证是,如果字符串包含有效的 Unicode,则可以使用 str String 在恒定时间内将其转换为 OsStr::to_strOsString::into_string 。您还可以使用 std::os::windows::ffi::OsStrExt::encode_wide 将字符串转换回可能格式错误的 UTF-16。

不直接访问原始字节的动机是几乎没有库期望字符串编码为 WTF-8。事实上,有些库甚至可能不希望使用 UTF-8! (他们可能会期望在 current "ANSI" code page 中编码的字符串。)如果事实证明库不期望 UTF-8 字符串,您应该改为使用 WideCharToMultiByte 将可能格式错误的 UTF-16 字符串转换为预期的编码。

关于rust - 如何将 Windows OsString 转换为 CString?,我们在Stack Overflow上找到一个类似的问题:https://stackoverflow.com/questions/54374381/

10-13 07:05