Rust Windows系统API生成库windows_gen的使用:高效调用Windows原生接口与功能
Rust Windows系统API生成库windows_gen的使用:高效调用Windows原生接口与功能
关于windows_gen
这个crate已经废弃。请查看windows-rs仓库获取更多信息。
安装方法
在项目目录中运行以下Cargo命令:
cargo add windows_gen
或者在Cargo.toml中添加以下行:
windows_gen = "0.31.0"
完整示例代码
虽然windows_gen已被废弃,但这里提供一个使用windows-rs(它的替代品)调用Windows API的完整示例:
use windows::{
core::*,
Win32::Foundation::*,
Win32::System::Threading::*,
Win32::System::WindowsProgramming::*,
};
fn main() -> Result<()> {
unsafe {
// 创建一个事件对象
let event = CreateEventW(
None, // 安全属性
true, // 手动重置事件
false, // 初始状态为非信号状态
None, // 事件名称
)?;
// 检查事件是否创建成功
if event.is_null() {
return Err(Error::from_win32());
}
// 设置事件为信号状态
SetEvent(event)?;
// 等待事件被触发
WaitForSingleObject(event, 0)?;
// 关闭事件句柄
CloseHandle(event)?;
Ok(())
}
}
代码说明:
CreateEventW
- 创建一个事件对象SetEvent
- 将事件设置为信号状态WaitForSingleObject
- 等待事件对象CloseHandle
- 关闭句柄
另一个完整示例
以下是一个使用windows-rs创建窗口的完整示例:
use windows::{
core::*,
Win32::Foundation::*,
Win32::System::LibraryLoader::*,
Win32::UI::WindowsAndMessaging::*,
};
unsafe extern "system" fn window_proc(
hwnd: HWND,
msg: u32,
wparam: WPARAM,
lparam: LPARAM,
) -> LRESULT {
match msg {
WM_DESTROY => {
PostQuitMessage(0);
LRESULT(0)
}
_ => DefWindowProcA(hwnd, msg, wparam, lparam),
}
}
fn main() -> Result<()> {
unsafe {
// 注册窗口类
let class_name = s!("MyWindowClass");
let hinstance = GetModuleHandleA(None)?;
let wnd_class = WNDCLASSA {
hInstance: hinstance,
lpfnWndProc: Some(window_proc),
lpszClassName: class_name,
..Default::default()
};
if RegisterClassA(&wnd_class) == 0 {
return Err(Error::from_win32());
}
// 创建窗口
let hwnd = CreateWindowExA(
0,
class_name,
s!("My Window"),
WS_OVERLAPPEDWINDOW,
CW_USEDEFAULT,
CW_USEDEFAULT,
CW_USEDEFAULT,
CW_USEDEFAULT,
None,
None,
hinstance,
None,
);
if hwnd.is_null() {
return Err(Error::from_win32());
}
// 显示窗口
ShowWindow(hwnd, SW_SHOW);
// 消息循环
let mut msg = MSG::default();
while GetMessageA(&mut msg, None, 0, 0).into() {
TranslateMessage(&msg);
DispatchMessageA(&msg);
}
Ok(())
}
}
元数据
- 版本: 0.31.0
- 发布时间: 约3年前
- 版本: 2018 edition
- 许可证: MIT OR Apache-2.0
- 大小: 732 B
所有者
- Yosh (yoshuawuyts)
- Kenny Kerr (kennykerr)
注意:windows_gen已被废弃,建议使用其替代品windows-rs来调用Windows API。
1 回复
Rust Windows系统API生成库windows_gen使用指南
介绍
windows_gen
是一个Rust库,用于高效生成和调用Windows原生API的绑定。它提供了类型安全的接口来访问Windows系统功能,避免了手动编写FFI绑定的繁琐工作。
该库的主要特点:
- 自动生成Windows API绑定
- 类型安全的接口
- 支持最新的Windows API
- 简化复杂API的调用
- 与Rust生态无缝集成
安装
在Cargo.toml中添加依赖:
[dependencies]
windows_gen = "0.9"
基本使用方法
1. 调用简单API
use windows_gen::Win32::System::Threading;
fn main() {
// 获取当前线程ID
let thread_id = Threading::GetCurrentThreadId();
println!("Current thread ID: {}", thread_id);
// 休眠500毫秒
Threading::Sleep(500);
}
2. 创建窗口示例
use windows_gen::Win32::{
Foundation::*,
UI::WindowsAndMessaging::*,
};
unsafe extern "system" fn wnd_proc(
hwnd: HWND,
msg: u32,
wparam: WPARAM,
lparam: LPARAM,
) -> LRESULT {
match msg {
WM_DESTROY => {
PostQuitMessage(0);
LRESULT(0)
}
_ => DefWindowProcW(hwnd, msg, wparam, lparam),
}
}
fn main() -> Result<()> {
unsafe {
let instance = GetModuleHandleW(None)?;
let window_class = WNDCLASSW {
lpfnWndProc: Some(wnd_proc),
hInstance: instance,
lpszClassName: PCWSTR(b"RustWindow\0".as_ptr()),
..Default::default()
};
RegisterClassW(&window_class);
CreateWindowExW(
WINDOW_EX_STYLE::default(),
PCWSTR(b"RustWindow\0".as_ptr()),
PCWSTR(b"Hello Windows\0".as_ptr()),
WS_OVERLAPPEDWINDOW,
CW_USEDEFAULT,
CW_USEDEFAULT,
CW_USEDEFAULT,
CW_USEDEFAULT,
None,
None,
instance,
None,
);
let mut msg = MSG::default();
while GetMessageW(&mut msg, None, 0, 0).into() {
TranslateMessage(&msg);
DispatchMessageW(&msg);
}
Ok(())
}
}
3. 文件操作示例
use windows_gen::Win32::Storage::FileSystem;
fn read_file_contents(path: &str) -> Result<Vec<u8>> {
unsafe {
let file = FileSystem::CreateFileW(
PCWSTR(path.encode_utf16().collect::<Vec<_>>().as_ptr()),
FileSystem::GENERIC_READ,
FileSystem::FILE_SHADE_READ,
None,
FileSystem::OPEN_EXISTING,
FileSystem::FILE_ATTRIBUTE_NORMAL,
None,
)?;
let mut buffer = Vec::new();
let mut bytes_read = 0;
FileSystem::ReadFile(
file,
Some(&mut buffer),
Some(&mut bytes_read),
None,
)?;
Ok(buffer)
}
}
高级功能
1. 异步API调用
use windows_gen::Win32::System::IO::{
self, OVERLAPPED, OVERLAPPED_0_0, HANDLE
};
use std::ptr;
async fn async_read_file(file: HANDLE, buffer: &mut [u8]) -> Result<()> {
let mut overlapsed = OVERLAPPED {
Anonymous: OVERLAPPED_0_0 { Offset: 0, OffsetHigh: 0 },
hEvent: CreateEventW(None, true, false, None)?,
Internal: 0,
InternalHigh: 0,
};
unsafe {
IO::ReadFile(
file,
Some(buffer),
None,
Some(&mut overlapped),
)?;
// 等待异步操作完成
IO::GetOverlappedResult(file, &overlapped, true)?;
}
Ok(())
}
2. COM组件调用
use windows_gen::Win32::System::Com;
fn com_example() -> Result<()> {
unsafe {
// 初始化COM
Com::CoInitializeEx(None, Com::COINIT_MULTITHREADED)?;
// 创建COM对象
let mut shell: Com::IShellItem = ptr::null_mut();
Com::CoCreateInstance(
&Com::CLSID_ShellItem,
None,
Com::CLSCTX_INPROC_SERVER,
&Com::IID_IShellItem,
&mut shell as *mut _ as *mut _,
)?;
// 使用COM对象
let mut display_name = PWSTR::null();
shell.GetDisplayName(Com::SIGDN_NORMALDISPLAY, &mut display_name)?;
println!("Display name: {}", display_name.to_string()?);
// 释放COM对象
shell.Release();
// 反初始化COM
Com::CoUninitialize();
Ok(())
}
}
最佳实践
- 错误处理:总是检查API调用的返回值,使用
?
操作符简化错误处理 - 内存安全:注意Windows API可能返回需要手动释放的资源
- 字符串转换:使用
PCWSTR
和PWSTR
类型处理Windows字符串 - 线程安全:了解API的线程安全要求,必要时使用同步原语
- 性能考虑:批量API调用通常比多次单独调用更高效
常见问题
-
如何找到特定的API:
- 查阅
windows_gen
文档 - 根据Windows API文档中的头文件路径查找对应模块
- 查阅
-
处理宽字符字符串:
use windows_gen::core::PWSTR; let wide_str: Vec<u16> = "Hello".encode_utf16().collect(); let pstr = PWSTR(wide_str.as_ptr() as *mut _);
-
处理返回的缓冲区:
unsafe { let mut buffer: Vec<u8> = Vec::with_capacity(1024); let mut size = buffer.capacity() as u32; if SomeApiFunction(buffer.as_mut_ptr(), &mut size) { buffer.set_len(size as usize); // 使用buffer... } }
完整示例:系统托盘应用
use windows_gen::Win32::{
Foundation::*,
UI::WindowsAndMessaging::*,
System::LibraryLoader::GetModuleHandleW,
};
// 窗口过程函数
unsafe extern "system" fn wnd_proc(
hwnd: HWND,
msg: u32,
wparam: WPARAM,
lparam: LPARAM,
) -> LRESULT {
match msg {
WM_CREATE => {
// 创建系统托盘图标
let mut nid = NOTIFYICONDATAW {
cbSize: std::mem::size_of::<NOTIFYICONDATAW>() as u32,
hWnd: hwnd,
uID: 1,
uFlags: NIF_ICON | NIF_MESSAGE | NIF_TIP,
uCallbackMessage: WM_APP,
hIcon: LoadIconW(None, IDI_APPLICATION),
szTip: [0; 128],
..Default::default()
};
// 设置提示文本
let tip = "Rust Tray App\0".encode_utf16().collect::<Vec<_>>();
nid.szTip[..tip.len()].copy_from_slice(&tip);
Shell_NotifyIconW(NIM_ADD, &nid);
LRESULT(0)
}
WM_APP => {
// 处理托盘消息
if lparam.0 as u32 == WM_RBUTTONUP {
let hmenu = CreatePopupMenu();
AppendMenuW(hmenu, MF_STRING, 1, PCWSTR(b"Exit\0".as_ptr()));
let mut pt = POINT::default();
GetCursorPos(&mut pt);
SetForegroundWindow(hwnd);
let cmd = TrackPopupMenu(
hmenu,
TPM_RETURNCMD,
pt.x,
pt.y,
0,
hwnd,
None,
);
if cmd == 1 {
PostQuitMessage(0);
}
}
LRESULT(0)
}
WM_DESTROY => {
// 移除托盘图标
let mut nid = NOTIFYICONDATAW {
cbSize: std::mem::size_of::<NOTIFYICONDATAW>() as u32,
hWnd: hwnd,
uID: 1,
..Default::default()
};
Shell_NotifyIconW(NIM_DELETE, &nid);
PostQuitMessage(0);
LRESULT(0)
}
_ => DefWindowProcW(hwnd, msg, wparam, lparam),
}
}
fn main() -> Result<()> {
unsafe {
let instance = GetModuleHandleW(None)?;
// 注册窗口类
let window_class = WNDCLASSW {
lpfnWndProc: Some(wnd_proc),
hInstance: instance,
lpszClassName: PCWSTR(b"RustTrayApp\0".as_ptr()),
..Default::default()
};
RegisterClassW(&window_class);
// 创建隐藏窗口
CreateWindowExW(
WINDOW_EX_STYLE::default(),
PCWSTR(b"RustTrayApp\0".as_ptr()),
PCWSTR(b"Tray App\0".as_ptr()),
WS_OVERLAPPEDWINDOW,
0, 0, 0, 0,
None,
None,
instance,
None,
);
// 消息循环
let mut msg = MSG::default();
while GetMessageW(&mut msg, None, 0, 0).into() {
TranslateMessage(&msg);
DispatchMessageW(&msg);
}
Ok(())
}
}
windows_gen
为Rust开发者提供了高效访问Windows API的能力,结合Rust的安全特性,可以构建既安全又高性能的Windows应用程序。