I have an std::ffi::OsString
on Windows, but I need to pass a std::ffi::CString
to an FFI function. Is there any way to convert the OsString
into the CString
?
I know that on Windows, OsString
is backed by a WTF-8-encoded buffer. Essentially all that needs to happen is to append an ASCII nul
character and create a CString from it. Is there a good way to do that? If not, is is possible to access that buffer directly?
Here is some example code:
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())
}
On Unix-like systems, you can obtain the raw bytes of an OsStr
or OsString
as a &[u8]
via std::os::unix::ffi::OsStrExt::as_bytes
. You can pass that slice directly to CString::new
.
On Windows, you cannot obtain the raw bytes of an OsStr
or OsString
. The WTF-8 encoding is considered a private implementation detail. The only guarantee is that if the string contains valid Unicode, then it can be converted to a str
or String
in constant time, using OsStr::to_str
or OsString::into_string
. You can also convert the string back to potentially ill-formed UTF-16 with std::os::windows::ffi::OsStrExt::encode_wide
.
The motivation for not giving direct access to the raw bytes is that almost no library expects strings encoded as WTF-8. In fact, some libraries might not even expect UTF-8! (They might instead expect strings encoded in the current "ANSI" code page.) If it turns out that the library doesn't expect UTF-8 strings, you should instead convert the potentially ill-formed UTF-16 string to the expected encoding using WideCharToMultiByte
.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With