如何在Rust中使用LPARAM向EnumWindows()传递元组
解决Rust中通过PID获取主窗口HWND的编译错误
你的代码主要存在两个核心问题:
- 传递给
EnumWindows的是临时元组的指针,该元组生命周期仅覆盖当前表达式,EnumWindows执行期间指针会变成悬垂指针,编译器会因生命周期不匹配报错。 - 回调中对
LPARAM的类型转换与传递的元组类型不完全匹配,导致类型错误。
以下是修正后的代码:
use winapi::um::winuser::{EnumWindows, GetWindowThreadProcessId}; use winapi::um::processthreadsapi::OpenProcess; use winapi::um::handleapi::CloseHandle; use winapi::um::winnt::PROCESS_QUERY_INFORMATION; use winapi::shared::minwindef::{DWORD, LPARAM, BOOL, TRUE, FALSE}; use winapi::shared::windef::HWND; use winapi::shared::ntdef::HANDLE; fn get_main_window_handle_from_pid(pid: DWORD) -> Option<HWND> { let mut hwnd = None; let process_handle = unsafe { OpenProcess(PROCESS_QUERY_INFORMATION, TRUE, pid) }; if !process_handle.is_null() { // 创建局部变量保存需要传递的数据,确保生命周期覆盖EnumWindows调用 let mut data = (hwnd, pid, process_handle); unsafe { EnumWindows(Some(enum_windows_callback), LPARAM(&mut data as *mut _ as isize)); CloseHandle(process_handle); } // 从data中取出最终的hwnd值 data.0 } else { None } } unsafe extern "system" fn enum_windows_callback(hwnd: HWND, lparam: LPARAM) -> BOOL { // 将LPARAM转换回原元组的可变引用 let data = &mut *(lparam.0 as *mut (Option<HWND>, DWORD, HANDLE)); let mut window_pid = 0; GetWindowThreadProcessId(hwnd, &mut window_pid); if window_pid == data.1 { // 找到匹配PID的窗口,保存HWND并终止枚举 data.0 = Some(hwnd); FALSE } else { // 继续枚举 TRUE } }
关键改动说明
- 生命周期修正:用局部变量
data存储需要传递的hwnd、pid和process_handle,确保其生命周期覆盖EnumWindows的整个执行过程,避免悬垂指针。 - 类型匹配修正:统一使用
HANDLE类型表示进程句柄,回调中转换回的类型与传递的元组类型完全一致,消除类型不匹配错误。 - 返回值规范:回调函数返回
BOOL类型(TRUE/FALSE),符合Win32 API的要求,原代码返回i32虽然值一致,但类型不严谨。 - 结果传递:枚举结束后从
data中取出最终的hwnd值,确保正确捕获回调中设置的结果。
内容的提问来源于stack exchange,提问作者user23034428
相关产品推荐
相关产品推荐

