编者注:此代码示例来自1.0之前的Rust版本,并且不是有效的Rust 1.0代码,但答案仍然包含有价值的信息。
我想将字符串文字传递给Windows API。许多Windows函数使用UTF-16作为字符串编码,而Rust的本机字符串是UTF-8。
我知道Rust有utf16_units()生成一个UTF-16字符迭代器,但我不知道如何使用该函数生成一个UTF-16字符串,其中零作为最后一个字符。
我正在制作这样的UTF-16字符串,但我确信有更好的方法来制作它:
extern "system" {
pub fn MessageBoxW(hWnd: int, lpText: *const u16, lpCaption: *const u16, uType: uint) -> int;
}
pub fn main() {
let s1 = [
'H' as u16, 'e' as u16, 'l' as u16, 'l' as u16, 'o' as u16, 0 as u16,
];
unsafe {
MessageBoxW(0, s1.as_ptr(), 0 as *const u16, 0);
}
}
答案 0 :(得分:8)
str::encode_utf16
是UTF-16值的稳定迭代器。
您只需要在该迭代器上使用collect()
来构建Vec<u16>
,然后在该向量上构建push(0)
:
pub fn main() {
let s = "Hello";
let mut v: Vec<u16> = s.encode_utf16().collect();
v.push(0);
}
str::utf16_units()
/ str::encode_utf16
不稳定。另一种方法是切换到夜间(如果您正在编写程序,而不是库,这是一个可行的选项)或使用像encoding这样的外部包:
extern crate encoding;
use std::slice;
use encoding::all::UTF_16LE;
use encoding::{Encoding, EncoderTrap};
fn main() {
let s = "Hello";
let mut v: Vec<u8> = UTF_16LE.encode(s, EncoderTrap::Strict).unwrap();
v.push(0); v.push(0);
let s: &[u16] = unsafe { slice::from_raw_parts(v.as_ptr() as *const _, v.len()/2) };
println!("{:?}", s);
}
(如果您想要&mut [u16]
),可以使用from_raw_parts_mut
。
但是,在此特定示例中,您必须小心使用字节序,因为UTF_16LE
编码为您提供了以小端字节顺序表示u16
的字节向量,而from_raw_parts
技巧允许您在平台的字节顺序中“查看”字节向量作为u16
的切片,这也可能是大端。如果您想要完全可移植性,那么使用像byteorder
这样的包可能会有所帮助。
This关于Reddit的讨论也可能有所帮助。
答案 1 :(得分:2)
对于静态 UTF-16 字符串,utf16_lit
crate 提供了一个易于使用的宏来在编译时执行此操作:
use utf16_lit::utf16_null;
fn main() {
let s = &utf16_null!("Hello");
println!("{:?}", s);
}
答案 2 :(得分:0)