如何从原始 C 字符串(CStr 或 *const u8)获取路径?

Kor*_*nel 12 c-strings ffi rust

使用 C 字符串作为 Rust 字符串的最直接方法是什么Path

const char *从 FFI 获得并需要将其用作 Rust 中的文件系统路径。

  • 我不想在路径上强制使用 UTF-8,因此通过str/进行转换String是不可取的。
  • 它应该至少在 Windows 上适用于 ASCII 路径。

fopen澄清一下:我只是用 Rust stdlib 实现替换将路径传递给的现有 C 实现。对于给定的文件系统来说,无论它是有效路径还是正确编码,这都不是我的问题,只要它不比fopen(而且我知道fopen基本上在 Windows 上不起作用)更差。

Kor*_*nel 5

这是我学到的:

\n\n
    \n
  • Path/OsStr在 Windows 上总是使用 WTF-8,并且在 Unix 上是一个与编码无关的字节包。

  • \n
  • 他们从不使用任何“宽”编码(如 UTF-16 或 UCS-2)存储任何路径。仅 Windows 的伪装OsStr只是隐藏 WTF-8 编码,仅此而已。

  • \n
  • 它不太可能永远改变,因为标准库 API 支持创建UTF-8PathOsStr从 UTF-8进行创建&str,而无需任何内存分配或突变(即as_ref()受支持,并且其严格的 API 不留空间将其实现为除指针转换)。

  • \n
\n\n

仅限 Unix 的零拷贝版本(它甚至不依赖于任何实现细节):

\n\n
use std::ffi::{CStr,OsStr};\nuse std::path::Path;\nuse std::os::unix::ffi::OsStrExt;\n\nlet slice = CStr::from_ptr(c_null_terminated_string_ptr_here);\nlet osstr = OsStr::from_bytes(slice.to_bytes());\nlet path: &Path = osstr.as_ref();\n
Run Code Online (Sandbox Code Playgroud)\n\n

在 Windows 上,仅转换有效的 UTF-8 是 Rust 可以做的最好的事情,而无需OsString从代码单元创建 WTF-8:

\n\n
\xe2\x80\xa6\nlet str = ::std::str::from_utf8(slice.to_bytes()).expect("keep your surrogates paired");\nlet path: &Path = str.as_ref();\n
Run Code Online (Sandbox Code Playgroud)\n


DK.*_*DK. 3

安全便携?据我所知,没有办法。我的建议是要求使用 UTF-8,并祈祷它永远不会中断。

问题是,关于“C 字符串”,您唯一能真正说的是它是以 NUL 结尾的。关于它的编码方式,您确实无法说出任何有意义的内容。至少,没有任何真正的确定性。

不安全和/或不可携带?如果您在 Linux(可能还有其他现代 *NIXen)上运行,则可以使用OsStrExt来进行转换。这仅在假设 C 字符串首先是有效路径的情况下才有效。如果它来自一些没有使用与文件系统相同的编码的字符串处理代码(现在通常是“看起来像 UTF-8 但可能不是的任意字节”)......那么,你必须先自己转换一下。

在 Windows 上? 哈哈哈哈。 这取决于字符串来自哪里。嵌入在可执行文件中的 C 字符串可以采用多种编码,具体取决于代码的编译方式。如果它来自操作系统本身,则它可能采用两种不同编码之一:线程的 OEM 代码页或线程的 ANSI 代码页。我从来没有弄清楚如何检查它的设置。如果它来自控制台,那么当您收到它时,它将采用控制台的输入编码设置...假设它不是从使用不同编码的其他东西通过管道传入的(嗨,PowerShell!)。上述所有内容都要求您编写自己的转码代码,因为 Rust 本身永远不会避免这种情况

哦,不要忘记没有8位编码可以正确存储 Windows 路径,因为 Windows 路径是“任意 16 位单词,看起来像 UTF-16,但可能不是”。[1]

...所以,就像我说的:要求 UTF-8 并祈祷它永远不会中断,因为试图“正确”地做到这一点会导致疯狂。


[1]:我应该澄清一下:有这样一种编码:WTF-8,这是 Rust 在 Windows 上使用的OsStr编码OsString。问题是 Windows 上没有其他任何东西使用它,所以它永远不会成为 C 字符串的编码方式。