A more convenient way to work with strings in winapi calls

I am looking for a more convenient way to work with std::String in winapi calls in Rust.

Using rust v 0.12.0-nigtly with winapi 0.1.22 and user32-sys 0.1.1

Now I am using something like this:

 use winapi; use user32; pub fn get_window_title(handle: i32) -> String { let mut v: Vec<u16> = Vec::new(); v.reserve(255); let mut p = v.as_mut_ptr(); let len = v.len(); let cap = v.capacity(); let mut read_len = 0; unsafe { mem::forget(v); read_len = unsafe { user32::GetWindowTextW(handle as winapi::HWND, p, 255) }; if read_len > 0 { return String::from_utf16_lossy(Vec::from_raw_parts(p, read_len as usize, cap).as_slice()); } else { return "".to_string(); } } } 

I think this vector-based memory allocation is rather strange. So I'm looking for an easier way to drop LPCWSTR to std::String

+6
source share
1 answer

In your situation, you should always have a maximum of 255 bytes, so you can use an array instead of a vector. This reduces the entire template to a call to mem::uninitialized() , a call to as_mut_ptr() and a cut operation.

 unsafe { let mut v: [u16; 255] = mem::uninitialized(); let read_len = user32::GetWindowTextW( handle as winapi::HWND, v.as_mut_ptr(), 255, ); String::from_utf16_lossy(&v[0..read_len]) } 

If you want to use Vec , it’s easier there than to destroy vec and recreate it. You can write directly to Vec content and let Rust handle the rest.

 let mut v: Vec<u16> = Vec::with_capacity(255); unsafe { let read_len = user32::GetWindowTextW( handle as winapi::HWND, v.as_mut_ptr(), v.capacity(), ); v.set_len(read_len); // this is undefined behavior if read_len > v.capacity() String::from_utf16_lossy(&v) } 

As a side note, Rust is idiomatic not to use return in the last statement in a function, but just to let the expression stand there without a semicolon. In the source code, the final if-expression can be written as

 if read_len > 0 { String::from_utf16_lossy(Vec::from_raw_parts(p, read_len as usize, cap).as_slice()) } else { "".to_string() } 

but I removed all the condition from my samples, since there is no need to handle characters 0 other than characters n .

+3
source

Source: https://habr.com/ru/post/989169/


All Articles