C++ vs Rust 实现 Windows 桌面时钟性能与开发效率对比
学习笔记作者:admin日期:2025-05-24点击:350
摘要:对比 C++ 和 Rust 实现 Windows 桌面时钟的性能、开发效率、安全性等方面,提供基于 Rust 的完整代码示例。
桌面时钟实现与技术对比
项目背景
本项目旨在使用 C++ 和 Rust 分别实现一个 Windows 桌面时钟程序,要求窗口始终置顶、每 2 秒更新时间。
C++ vs Rust 对比
| 维度 | C++ (Win32) | Rust (Win32) | Rust (egui/winit) | 
|---|---|---|---|
| 性能 | 极高 | 极高 | 高 | 
| 安全性 | 低(手动管理) | 高(借用检查) | 高 | 
| 开发效率 | 低 | 中等 | 高 | 
| 可维护性 | 差 | 好 | 很好 | 
| 跨平台 | 否 | 否(封装) | 是 | 
| 易学程度 | 高 | 中等 | 中等 | 
Rust 实现代码示例
extern crate winapi;
use std::ffi::OsStr;
use std::os::windows::ffi::OsStrExt;
use std::ptr::null_mut;
use std::time::{SystemTime, UNIX_EPOCH};
use winapi::shared::minwindef::*;
use winapi::shared::ntdef::*;
use winapi::um::libloaderapi::*;
use winapi::um::winuser::*;
const IDT_TIMER: usize = 1;
fn main() {
    unsafe {
        let h_instance = GetModuleHandleW(null_mut());
        let class_name: Vec = OsStr::new("ClockWindowClass")
            .encode_wide()
            .chain(Some(0).into_iter())
            .collect();
        let wnd_class = WNDCLASSW {
            style: 0,
            lpfnWndProc: Some(wnd_proc),
            cbClsExtra: 0,
            cbWndExtra: 0,
            hInstance: h_instance,
            hIcon: LoadIconW(null_mut(), IDI_APPLICATION),
            hCursor: LoadCursorW(null_mut(), IDC_ARROW),
            hbrBackground: (COLOR_WINDOW + 1) as HBRUSH,
            lpszMenuName: null_mut(),
            lpszClassName: class_name.as_ptr(),
        };
        RegisterClassW(&wnd_class);
        let hwnd = CreateWindowExW(
            WS_EX_TOPMOST,
            class_name.as_ptr(),
            to_wstring("桌面时钟").as_ptr(),
            WS_POPUP | WS_VISIBLE,
            CW_USEDEFAULT,
            CW_USEDEFAULT,
            300,
            100,
            null_mut(),
            null_mut(),
            h_instance,
            null_mut(),
        );
        if hwnd.is_null() {
            return;
        }
        SetTimer(hwnd, IDT_TIMER as UINT_PTR, 2000, None);
        ShowWindow(hwnd, SW_SHOW);
        UpdateWindow(hwnd);
        let mut msg: MSG = std::mem::zeroed();
        while GetMessageW(&mut msg, null_mut(), 0, 0) > 0 {
            TranslateMessage(&msg);
            DispatchMessageW(&msg);
        }
    }
}
unsafe extern "system" fn wnd_proc(
    hwnd: HWND,
    msg: UINT,
    wparam: WPARAM,
    lparam: LPARAM,
) -> LRESULT {
    static mut TIME_STR: [u16; 64] = [0; 64];
    match msg {
        WM_CREATE => {
            get_time_string(&mut TIME_STR);
            SetTimer(hwnd, IDT_TIMER as UINT_PTR, 2000, None);
            0
        }
        WM_TIMER => {
            if wparam == IDT_TIMER {
                get_time_string(&mut TIME_STR);
                InvalidateRect(hwnd, std::ptr::null(), TRUE);
            }
            0
        }
        WM_PAINT => {
            let mut ps: PAINTSTRUCT = std::mem::zeroed();
            let hdc = BeginPaint(hwnd, &mut ps);
            let rect: RECT = {
                let mut r = std::mem::zeroed();
                GetClientRect(hwnd, &mut r);
                r
            };
            DrawTextW(
                hdc,
                TIME_STR.as_ptr(),
                TIME_STR.iter().position(|&c| c == 0).unwrap_or(TIME_STR.len()) as i32,
                &rect,
                DT_CENTER | DT_VCENTER | DT_SINGLELINE,
            );
            EndPaint(hwnd, &ps);
            0
        }
        WM_DESTROY => {
            KillTimer(hwnd, IDT_TIMER as UINT_PTR);
            PostQuitMessage(0);
            0
        }
        _ => DefWindowProcW(hwnd, msg, wparam, lparam),
    }
}
fn get_time_string(buf: &mut [u16; 64]) {
    let now = SystemTime::now()
        .duration_since(UNIX_EPOCH)
        .unwrap()
        .as_secs();
    let tm = unsafe { *localtime(&now as *const u64 as *const i64) };
    let mut time_str = [0u8; 64];
    unsafe {
        strftime(
            time_str.as_mut_ptr() as *mut i8,
            time_str.len(),
            b"%Y-%m-%d %H:%M:%S\0".as_ptr() as *const i8,
            &tm,
        );
    }
    let utf16: Vec<u16> = OsStr::from_bytes(&time_str)
        .encode_wide()
        .take_while(|&c| c != 0)
        .collect();
    for (i, &c) in utf16.iter().enumerate() {
        buf[i] = c;
    }
    buf[utf16.len()] = 0;
}
fn to_wstring(s: &str) -> Vec<u16> {
    OsStr::new(s)
        .encode_wide()
        .chain(Some(0))
        .collect()
} 总结
Rust 在保持高性能的同时提供了更高的安全性、开发效率和可维护性,是现代桌面开发的优秀选择。