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(())
    }
}

代码说明:

  1. CreateEventW - 创建一个事件对象
  2. SetEvent - 将事件设置为信号状态
  3. WaitForSingleObject - 等待事件对象
  4. 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(())
    }
}

最佳实践

  1. 错误处理:总是检查API调用的返回值,使用?操作符简化错误处理
  2. 内存安全:注意Windows API可能返回需要手动释放的资源
  3. 字符串转换:使用PCWSTRPWSTR类型处理Windows字符串
  4. 线程安全:了解API的线程安全要求,必要时使用同步原语
  5. 性能考虑:批量API调用通常比多次单独调用更高效

常见问题

  1. 如何找到特定的API

    • 查阅windows_gen文档
    • 根据Windows API文档中的头文件路径查找对应模块
  2. 处理宽字符字符串

    use windows_gen::core::PWSTR;
    
    let wide_str: Vec<u16> = "Hello".encode_utf16().collect();
    let pstr = PWSTR(wide_str.as_ptr() as *mut _);
    
  3. 处理返回的缓冲区

    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应用程序。

回到顶部