2017-11-28 3 views
-2

Ich habe Probleme mit dem Aufruf der Wide-Char-Version von GetUserName. Der UTF-8-Aufruf funktioniert, obwohl es möglicherweise eine bessere Möglichkeit gibt, dies zu tun: # [cfg (windows)] extern crate advapi32; # [cfg (windows)] extern kiste winapi;WinAPI mit OsString aufrufen und zurück in String konvertieren

use std::ffi::CString; 

fn get_user_name() -> String { 
    let mut sz: u32 = 64; 
    unsafe { 
     let mut username = CString::from_vec_unchecked(vec![0; sz as usize]); 
     let ptr = username.into_raw(); 
     advapi32::GetUserNameA(ptr as *mut i8, &mut sz as *mut u32); 
     CString::from_raw(ptr).to_str().unwrap().to_owned() 
    } 
} 

Dann habe ich die UTF-16-Version versucht. Das funktioniert, sieht aber falsch aus, da ich diese leere Zeichenfolge für OsStr::new() erstellen muss.

fn get_user_name() -> String { 
    // for windows 
    use std::ffi::OsStr; 
    let mut sz: u32 = 64; 
    let mut username = OsStr::new("       ") 
     .encode_wide() 
     .collect::<Vec<u16>>(); 
    unsafe { 
     advapi32::GetUserNameW(username.as_mut_ptr() as *mut u16, &mut sz as *mut u32); 
    } 
    String::from_utf16(&username[..sz as usize]).unwrap() 
} 

ich versuchte, mit OsString::with_capacity() aber diese Abstürze:

fn get_user_name() -> String { 
    // for windows 
    use std::ffi::OsStr; 
    let mut sz: u32 = 64; 
    let mut username = OsString::with_capacity(sz as usize) 
     .as_os_str() 
     .encode_wide() 
     .collect::<Vec<u16>>(); 
    unsafe { 
     advapi32::GetUserNameW(username.as_mut_ptr() as *mut u16, &mut sz as *mut u32); 
    } 
    String::from_utf16(&username[..sz as usize]).unwrap() 
} 

Es gibt andere Antworten auf Stack-Überlauf, wo Rust eine Zeichenfolge erstellt in eine Funktion zu übergeben (zB MessageBoxW), aber keine, wo die Größe ist bestimmt von Windows und Rust muss Speicherplatz reservieren, um später bestückt zu werden.

Wie lautet die korrekte Methode zum Aufrufen einer Wide-Char-Funktion unter Windows, bei der Rust einen Puffer vorbelegen und dann (eventuell) in eine Standard-UTF-8-Zeichenfolge konvertieren muss?

+2

I die Puffer passieren würde direkt von '' Vec /'' Vec Zuteilungen (oder Arrays auf dem Stapel ...); Konvertiere sie in Strings ** nachdem ** sie gefüllt wurden. – Stefan

+2

@Ronnie Bitte posten Sie die Antwort als eine richtige Antwort, danke. – kennytm

+1

** Sie ** gefragt [Aufruf der WinAPI-Funktion GetUserName mit einer veränderbaren Zeichenfolge füllt die Zeichenfolge nicht] (https://stackoverflow.com/q/44709780/155423), so würde man erwarten, dass Sie sich an die Antwort erinnern. – Shepmaster

Antwort

-1

Von den Kommentaren, mit Vec direkt ist der einfachste Ansatz.

fn get_user_name() -> String { 
    // for windows 
    let mut sz: u32 = 64; 
    let mut username: Vec<u16> = vec![0; sz as usize]; 
    unsafe { 
     advapi32::GetUserNameW(username.as_mut_ptr() as *mut u16, &mut sz as *mut u32); 
    } 
    String::from_utf16(&username[..sz as usize]).unwrap() 
} 
+0

Dieser Code kann den Rückgabewert von 'GetUserNameW' nicht überprüfen und ist daher sehr unsicher. – Shepmaster

Verwandte Themen