Rust Windows系统API宏库windows_macros的使用,简化Windows平台系统级编程与FFI调用
Rust Windows系统API宏库windows_macros的使用
关于windows_macros
该crate已弃用。建议使用新的windows-rs
库。
安装
在项目目录中运行以下Cargo命令:
cargo add windows_macros
或者在Cargo.toml中添加以下行:
windows_macros = "0.31.0"
许可证
该库采用MIT或Apache-2.0许可证。
所有者
- Kenny Kerr (kennykerr)
示例代码
以下是windows_macros可能的使用方式示例:
// 引入windows_macros库
#[macro_use]
extern crate windows_macros;
// 使用宏定义Windows API绑定
define_api! {
fn MessageBoxA(
hWnd: HANDLE,
lpText: LPCSTR,
lpCaption: LPCSTR,
uType: UINT
) -> INT;
}
fn main() {
unsafe {
// 调用Windows API
MessageBoxA(
std::ptr::null_mut(),
"Hello from Rust!\nThis is a Windows API call".as_ptr() as LPCSTR,
"Rust Windows API".as_ptr() as LPCSTR,
0
);
}
}
完整示例代码
以下是一个更完整的示例,展示如何使用windows_macros调用多个Windows API:
// 引入必要的库
#[macro_use]
extern crate windows_macros;
use std::ffi::CString;
// 定义多个Windows API
define_api! {
fn MessageBoxA(
hWnd: HANDLE,
lpText: LPCSTR,
lpCaption: LPCSTR,
uType: UINT
) -> INT;
fn GetLastError() -> DWORD;
fn GetCurrentProcessId() -> DWORD;
}
fn main() {
unsafe {
// 调用GetCurrentProcessId获取当前进程ID
let pid = GetCurrentProcessId();
println!("当前进程ID: {}", pid);
// 准备消息框内容
let text = CString::new("Hello from Rust!").unwrap();
let caption = CString::new("进程信息").unwrap();
// 调用MessageBoxA显示消息框
let result = MessageBoxA(
std::ptr::null_mut(),
text.as_ptr(),
caption.as_ptr(),
0
);
// 检查API调用结果
if result == 0 {
let error = GetLastError();
println!("MessageBoxA调用失败,错误代码: {}", error);
}
}
}
注意:windows_macros已弃用,建议使用新的windows-rs
库进行Windows API调用。
1 回复
Rust Windows系统API宏库windows_macros使用指南
windows_macros
是一个简化Windows平台系统级编程和FFI调用的Rust宏库,它提供了更符合Rust习惯的方式来调用Windows API。
主要特性
- 简化Windows API调用语法
- 自动类型转换和错误处理
- 减少FFI调用的样板代码
- 提供更符合Rust习惯的API封装
安装方法
在Cargo.toml中添加依赖:
[dependencies]
windows_macros = "0.1"
windows = "0.48" # 官方windows crate
基本使用方法
1. 调用Windows API
use windows_macros::winapi;
fn main() {
// 调用MessageBoxA
winapi! {
user32::MessageBoxA(
None,
"Hello from Rust!",
"Message",
windows::Win32::UI::WindowsAndMessaging::MB_OK
)
};
}
2. 带返回值的API调用
use windows_macros::winapi;
fn get_screen_width() -> Result<i32, windows::core::Error> {
winapi! {
user32::GetSystemMetrics(
windows::Win32::UI::WindowsAndMessaging::SM_CXSCREEN
) as i32
}
}
3. 处理输出参数
use windows_macros::winapi;
fn get_window_text(hwnd: isize) → Result<String, windows::core::Error> {
let mut text = [0u16; 256];
let len = winapi! {
user32::GetWindowTextW(
hwnd,
&mut text,
text.len() as i32
)
}?;
Ok(String::from_utf16_lossy(&text[..len as usize]))
}
高级用法
1. 调用COM接口
use windows_macros::com_call;
fn create_instance() -> Result<(), windows::core::Error> {
let mut punknown = std::ptr::null_mut();
com_call! {
CoCreateInstance(
&windows::Win32::System::Com::CLSID_FileOpenDialog,
None,
windows::Win32::System::Com::CLSCTX_INPROC_SERVER,
&windows::Win32::System::Com::IID_IFileOpenDialog,
&mut punknown
)
}?;
// 使用接口...
Ok(())
}
2. 自定义错误处理
use windows_macros::winapi_with_error;
fn set_window_pos(hwnd: isize, x: i32, y: i32) -> Result<(), String> {
winapi_with_error!(
|e| format!("SetWindowPos failed: {}", e),
user32::SetWindowPos(
hwnd,
windows::Win32::Foundation::HWND(0),
x, y, 0, 0,
windows::Win32::UI::WindowsAndMessaging::SWP_NOSIZE
)
)
}
宏参数说明
winapi!
: 基本API调用宏,自动处理错误转换com_call!
: 专门用于COM接口调用的宏winapi_with_error!
: 允许自定义错误处理的宏
注意事项
- 需要同时使用官方的
windows
crate - 宏调用会自动将错误转换为
windows::core::Error
- 对于输出参数,需要像普通Rust代码一样使用
&mut
传递 - 返回值的类型推断可能有时需要显式标注
性能考虑
windows_macros
在编译时展开为标准的Windows API调用,没有运行时开销,性能与直接使用windows
crate相当。
这个库特别适合需要频繁调用Windows API的系统级编程场景,可以显著减少样板代码并提高可读性。
完整示例DEMO
下面是一个完整的窗口创建示例,展示如何使用windows_macros创建Windows窗口:
use windows_macros::{winapi, winapi_with_error};
use windows::{
Win32::{
Foundation::*,
UI::WindowsAndMessaging::*,
Graphics::Gdi::*
},
core::*
};
// 窗口过程函数
unsafe extern "system" fn wnd_proc(
hwnd: HWND,
msg: u32,
wparam: WPARAM,
lparam: LPARAM
) -> LRESULT {
match msg {
WM_PAINT => {
let mut ps = PAINTSTRUCT::default();
let hdc = winapi! { BeginPaint(hwnd, &mut ps) };
// 绘制文本
let text = PCSTR("Hello from Rust\0".as_ptr());
winapi! { TextOutA(hdc, 50, 50, text, 15) };
winapi! { EndPaint(hwnd, &ps) };
LRESULT(0)
}
WM_DESTROY => {
winapi! { PostQuitMessage(0) };
LRESULT(0)
}
_ => winapi! { DefWindowProcA(hwnd, msg, wparam, lparam) }
}
}
fn main() -> Result<(), windows::core::Error> {
// 注册窗口类
let class_name = PCSTR("RUST_WINDOW\0".as_ptr());
let wnd_class = WNDCLASSEXA {
cbSize: std::mem::size_of::<WNDCLASSEXA>() as u32,
style: CS_HREDRAW | CS_VREDRAW,
lpfnWndProc: Some(wnd_proc),
hInstance: winapi! { GetModuleHandleA(None) }?,
hCursor: winapi! { LoadCursorA(None, IDC_ARROW) }?,
hbrBackground: winapi! { GetStockObject(WHITE_BRUSH) }?,
lpszClassName: class_name,
..Default::default()
};
winapi! { RegisterClassExA(&wnd_class) }?;
// 创建窗口
let hwnd = winapi_with_error!(
|e| format!("CreateWindowEx failed: {}", e),
CreateWindowExA(
0,
class_name,
PCSTR("Rust Windows Example\0".as_ptr()),
WS_OVERLAPPEDWINDOW,
CW_USEDEFAULT,
CW_USEDEFAULT,
400,
300,
None,
None,
wnd_class.hInstance,
None
)
)?;
// 显示窗口
winapi! { ShowWindow(hwnd, SW_SHOW) };
winapi! { UpdateWindow(hwnd) };
// 消息循环
let mut msg = MSG::default();
while winapi! { GetMessageA(&mut msg, None, 0, 0) } != FALSE {
winapi! { TranslateMessage(&msg) };
winapi! { DispatchMessageA(&msg) };
}
Ok(())
}
这个完整示例展示了:
- 使用
winapi!
宏调用Windows API - 使用
winapi_with_error!
进行自定义错误处理 - 创建窗口、处理消息循环等完整流程
- 展示了如何使用输出参数和返回值处理