Как правильно распределить данные для передачи в вызов FFI?
Послеобсуждение / изучение правильного способа вызова FFI Windows-API из RustЯ немного поиграл с этим и хотел бы еще раз проверить мое понимание.
У меня есть Windows API, который вызывается дважды. При первом вызове он возвращает размер буфера, который понадобится для его фактического параметра out. Затем он вызывается второй раз с буфером достаточного размера. Я в настоящее время используюVec
как тип данных для этого буфера (см. пример ниже).
Код работает, но мне интересно, является ли это правильным способом сделать это или было бы лучше использовать такую функцию, какalloc::heap::allocate
напрямую зарезервировать часть памяти, а затем использоватьtransmute
конвертировать результат из FFI обратно. Опять же, мой код работает, но я пытаюсь немного заглянуть за кулисы.
extern crate advapi32;
extern crate winapi;
extern crate widestring;
use widestring::WideCString;
use std::io::Error as IOError;
use winapi::winnt;
fn main() {
let mut lp_buffer: Vec<winnt::WCHAR> = Vec::new();
let mut pcb_buffer: winapi::DWORD = 0;
let rtrn_bool = unsafe {
advapi32::GetUserNameW(lp_buffer.as_mut_ptr(),
&mut pcb_buffer )
};
if rtrn_bool == 0 {
match IOError::last_os_error().raw_os_error() {
Some(122) => {
// Resizing the buffers sizes so that the data fits in after 2nd
lp_buffer.resize(pcb_buffer as usize, 0 as winnt::WCHAR);
} // This error is to be expected
Some(e) => panic!("Unknown OS error {}", e),
None => panic!("That should not happen"),
}
}
let rtrn_bool2 = unsafe {
advapi32::GetUserNameW(lp_buffer.as_mut_ptr(),
&mut pcb_buffer )
};
if rtrn_bool2 == 0 {
match IOError::last_os_error().raw_os_error() {
Some(e) => panic!("Unknown OS error {}", e),
None => panic!("That should not happen"),
}
}
let widestr: WideCString = unsafe { WideCString::from_ptr_str(lp_buffer.as_ptr()) };
println!("The owner of the file is {:?}", widestr.to_string_lossy());
}
зависимости:
[dependencies]
advapi32-sys = "0.2"
winapi = "0.2"
widestring = "*"