前端UI组件3D渲染跨平台游戏开发【免费下载链接】makepadMakepad is a creative software development platform for Rust that compiles to wasm/webGL, osx/metal, windows/dx11 linux/opengl项目地址https://gitcode.com/gh_mirrors/ma/makepad点击查看免费下载导读本文围绕 Makepad 仓库中libs/windows/windows-result这一子 crate 展开系统讲解 Rust 下面向 Win32、COM 与 WinRT 的统一错误处理方案HRESULT错误码、携带扩展错误信息的Error类型以及专门化的ResultT。读完本文你将掌握如何在自己的 Rust 项目中接入 windows-result、正确使用S_OK.ok()?与?传播模式、理解from_win32的位运算映射规则以及通过windows_slim_errors配置把Error瘦身到 4 字节的底层原理。一、背景与定位Makepad 为什么需要 windows-resultMakepad 是一个面向 Rust 的跨平台创意软件开发平台编译目标覆盖 wasm/WebGL、macOS/Metal、Windows/DX11 与 Linux/OpenGL。在如此庞大的跨平台代码库中Windows 平台的实现代码需要一个统一、高效、可传播的错误处理基座既要兼容 Win32 API 的GetLastError风格错误码又要适配 COM 的HRESULT还要承接 WinRT 组件的扩展错误信息。windows-result正是承担这一职责的 crate它的核心设计目标由仓库源码直接印证提供带扩展错误信息IErrorInfoCOM 对象的Error类型支持在?运算符中自动传播、转换 Win32 / COM / WinRT 三类错误通过NonZeroI32的 niche 优化让Result(), Error保持在 8 字节甚至 4 字节详见后文windows_slim_errors可编译为no_std环境lib.rs 中以#![cfg_attr(all(not(feature std), not(test)), no_std)]控制。从源码结构看windows-core同样依赖windows_result说明它是整个 windows-rs 生态在 Makepad 仓库中共同的错误处理底层。二、快速开始添加依赖与第一个示例原文档给出的接入方式非常简洁在Cargo.toml中添加[dependencies.windows-result] version 0.4当前仓库实际打包的版本为0.4.1见 Cargo.toml默认开启std特性default [std]。crate 遵循MIT OR Apache-2.0双许可rust-version 1.82并在docs.rs上以x86_64-pc-windows-msvc为目标构建文档。随后即可按原文档示例使用HRESULT、Error和专门的Result类型use windows_result::*; const S_OK: HRESULT HRESULT(0); const ERROR_CANCELLED: u32 1223; const E_CANCELLED: HRESULT HRESULT::from_win32(ERROR_CANCELLED); fn main() - Result() { S_OK.ok()?; let e Error::new(E_CANCELLED, test message); assert_eq!(e.code(), E_CANCELLED); assert_eq!(e.message(), test message); Ok(()) }逐行拆解这段示例HRESULT(0)即S_OK是 COM 调用成功时的标准返回码HRESULT::from_win32(ERROR_CANCELLED)把 Win32 错误码 1223用户取消操作映射成 COM 错误码S_OK.ok()?是惯用写法成功码返回Ok(())失败码自动转换并交给?传播失败的传播路径见 hresult.rs 中ok()的实现Error::new(code, message)创建带自定义文本的错误对象code()与message()可分别取回错误码与消息。三、核心类型体系HRESULT、Error 与 Result3.1 HRESULTCOM 错误码的透明封装HRESULT是对底层i32的#[repr(transparent)]封装hresult.rs因此与原生HRESULT内存布局完全一致可无缝用于 FFI。其判据非常简单最高位为 0即self.0 0表示成功码最高位为 1 表示失败码据此实现方法作用实现要点is_ok()是否为成功码self.0 0is_err()是否为失败码!self.is_ok()unwrap()失败时 panic并打印0x{:X}格式的错误码带#[track_caller]可定位调用点ok()转换为Result()成功Ok(())失败Err(self.into())map(op)成功时执行op返回ResultT基于ok()?实现and_then(op)成功时执行返回ResultT的op基于ok()?实现message()取系统错误描述文本底层调用FormatMessageW见下文from_thread()读取当前线程GetLastError()并映射仅 Windows 生效from_win32(error)Win32 错误码 → HRESULT见第 4 节位运算from_nt(error)NT 错误码 → HRESULT失败时error \| 0x1000_0000此外HRESULT实现了Display输出#010X格式的十六进制、Debug、Copy/Clone/Eq/Hash等全套 trait并且FromResultT允许把整个Result转回HRESULT错误时取其中的错误码成功时为HRESULT(0)。3.2 Error错误码 可选扩展信息Error是承载完整错误上下文的结构体error.rs内部由两部分构成pub struct Error { code: NonZeroI32, // HRESULT 错误码用 NonZeroI32 提供 niche info: ErrorInfo, // 可选的 IErrorInfo COM 对象扩展信息 }关键设计点niche 优化code使用NonZeroI32编译器可利用零值不可能出现这一空隙让ResultT, Error的Ok/Err枚举判别更紧凑。由于S_OK0被占用内部用S_EMPTY_ERROR常量u32::from_be_bytes(*bS_OK)的 4 字节 ASCII 值来占位表示空错误code()取回时会还原为HRESULT(0)。常用构造方式Error::empty()无任何失败信息、Error::new(code, message)携带自定义消息Windows 下会调用RoOriginateErrorW登记 WinRT 错误来源、Error::from_hresult(code)仅错误码、Error::from_thread()从GetLastError()构造。trait 实现细节Debug输出code与message两个字段Display输出message (code)无消息时仅输出codePartialEq/Hash只比较错误码不比较扩展信息——这是刻意的设计代码注释明确说明 Equality tests only the HRESULT, not the error info使错误对象可以作为 map 键等场景使用。3.3 Result面向 Windows 的专门类型lib.rs 定义了pub type ResultT core::result::ResultT, Error;它复用了标准库Result的全部语法?、Ok/Err、map_err等但错误侧固定为Error从而与 windows-rs 生态的 API 无缝衔接。这正是原文档示例fn main() - Result()能够工作的基础。3.4 BOOL另一个成功/失败信号类型与HRESULT配套的还有BOOLbool.rs它封装 Win32 的 32 位布尔值提供as_bool()、ok()非零 →Ok(())零 →Error::from_thread()、unwrap()、expect(msg)等转换入口并实现了与bool的双向From转换及PartialEqbool让BOOL能直接与 Rustbool比较。四、错误码转换Win32 / NT / 线程错误到 HRESULTHRESULT的位布局是理解整套转换的关键。COM 错误码的高位是严重性位中 16 位是设施代码facility低 16 位是错误编号。from_win32的映射规则在 hresult.rs 中pub const fn from_win32(error: u32) - Self { Self(if error as i32 0 { error } else { (error 0x0000_FFFF) | (7 16) | 0x8000_0000 } as i32) }含义是若 Win32 错误码本身已 0已是失败形态直接采用否则保留低 16 位编号将设施代码置为 7FACILITY_WIN32并置位最高位的失败标志最终形如0x8007XXXX。这解释了原文档中ERROR_CANCELLED 1223映射为E_CANCELLED的来源。同理from_nt把 NT 状态码的失败值加上0x1000_0000FACILITY_NT标志而from_thread()则在 Windows 上通过GetLastError()拿到当前线程的 Win32 错误后调用from_win32从而在 COM 层统一线程最后错误。五、错误消息与 COM 扩展错误信息5.1 系统消息FormatMessageW 链路HRESULT::message()与Error::message()最终都落到系统消息查询。在 hresult.rs 中message()调用FormatMessageW并使用FORMAT_MESSAGE_ALLOCATE_BUFFER | FORMAT_MESSAGE_FROM_SYSTEM | FORMAT_MESSAGE_IGNORE_INSERTS组合标志若错误码命中0x1000_0000位NT 设施还会临时LoadLibraryExA加载ntdll.dll并从该模块取消息最后用wide_trim_end去掉 UTF-16 字符串尾部的空白strings.rs。分配出的缓冲区由HeapString管理生命周期Drop时通过HeapFree释放。在非 Windows 平台或 Windows 上取消息失败时message()退化为输出0x{:08x}格式的十六进制错误码保证跨平台调试信息仍然可读。5.2 扩展信息IErrorInfo / IRestrictedErrorInfoError的info字段在 Windows 下是一个ComPtr指向IErrorInfoCOM 对象com.rs、error.rs。ErrorInfo::message()的提取策略是先尝试把IErrorInfo通过QueryInterface强转为IRestrictedErrorInfoWinRT 受限错误信息接口IID见 bindings.rs调用GetErrorDetails获取更丰富的信息含 fallback 描述若拿不到再调用普通IErrorInfo::GetDescription取描述文本。ComPtr实现了引用计数的CloneAddRef与DropRelease并且Send/Sync可在线程间传递。Error::new在 Windows 下还会调用RoOriginateErrorW来自api-ms-win-core-winrt-error-l1-1-0.dll把错误登记进 WinRT 的错误来源系统这样 WinRT 组件可捕获堆栈等额外信息。六、windows_slim_errors把 Error 压到 4 字节这是 windows-result 最值得称道的工程决策之一。error.rs 的文档注释完整阐述了动机许多基于 COM 的系统并不使用IErrorInfo此时扩展信息字段毫无收益却因增大Error结构体而拖累ResultT的体积。通过编译期配置RUSTFLAGS--cfgwindows_slim_errors可以裁掉IErrorInfo支持获得三项收益Error缩小到4 字节即HRESULT本身的大小Result(), Error缩小到4 字节可以在单个机器寄存器中返回Error/Result不再需要Drop实现消除了生命周期检查与析构代码显著减小大量使用错误传播的代码库体积。代价是失去 COM 对象的扩展错误信息。值得注意的设计哲学是它被实现为--cfg标志而非 Cargo feature因为这是影响整个依赖图的全程序策略Error的尺寸必须全图一致而非某个 crate 可以单独决定的可加性特性。源码中check-cfg也显式声明了该配置Cargo.toml。七、与标准库生态的互操作开启std特性后默认开启Error实现了std::error::Error可直接用于Boxdyn std::error::Error等泛型错误场景FromError for std::io::Error通过FromRawOsError转成 OS 错误Fromstd::io::Error for Error反向转换raw_os_error存在时走HRESULT::from_win32否则使用E_UNEXPECTED。此外还有一组对常见转换失败的兜底映射例如FromUtf16Error/FromUtf8Error→ERROR_NO_UNICODE_TRANSLATION1113TryFromIntError→ERROR_INVALID_DATA13保证任何一处?传播都能收敛到 Windows 错误体系。这些常量定义在 bindings.rs 中。八、跨平台与 no_std 设计尽管 windows-result 面向 Windows 生态它仍然保持高度的可移植性不启用std时以no_std编译仅依赖allocString、Vec非 Windows 平台上HRESULT::from_thread()直接unimplemented!()Error::new忽略消息参数退化为from_hresultmessage()输出十六进制码——这让同源码可被其他平台的文档构建、静态检查与测试复用通过windows_link宏声明动态链接bindings.rs涉及kernel32.dllFormatMessageW、GetLastError、HeapFree、LoadLibraryExA、oleaut32.dllGetErrorInfo、SetErrorInfo、SysFreeString、SysStringLen与api-ms-win-core-winrt-error-l1-1-0.dllRoOriginateErrorW配套的windows-result.natvislibs/windows/windows-result/windows-result.natvis为 Visual Studio 调试器提供自定义可视化源码在 lib.rs 中以#![debugger_visualizer(natvis_file ../windows-result.natvis)]声明方便原生调试。九、在 Makepad 项目中的源码导航如果需要继续深入阅读可按以下顺序探索入口与类型导出src/lib.rs —— 模块划分与ResultT定义错误码核心src/hresult.rs ——HRESULT全部方法错误对象src/error.rs ——Error、niche 优化与windows_slim_errors策略说明COM 辅助src/com.rs ——ComPtr与com_call!宏平台绑定src/bindings.rs —— FFI 声明与常量依赖关系Cargo.toml —— 特性、版本与 lint 配置以及[dependencies.windows-link]指向同仓库的libs/windows/windows-link该目录位于libs/windows/下与windows-result并列。整体而言windows-result 用约 8 个源文件实现了 Win32 / COM / WinRT 三类错误的统一建模、消息提取、跨平台降级与极致体积优化是 Makepad 仓库中 Windows 平台代码错误处理的地基。理解它的设计也就理解了 windows-rs 生态中错误码 扩展信息 niche 优化这一整套可传播错误体系的工作方式。赞分享前端UI组件3D渲染跨平台游戏开发【免费下载链接】makepadMakepad is a creative software development platform for Rust that compiles to wasm/webGL, osx/metal, windows/dx11 linux/opengl项目地址https://gitcode.com/gh_mirrors/ma/makepad点击查看免费下载相关推荐深入解析 Sliver 仓库中的 mailgun/errorsGo 结构化错误处理库深入解析 Sliver 仓库中的 mailgun/errorsGo 结构化错误处理库 SliverAdversary Emulation Framework网络安全Makepad 仓库中的 windows-future用 Rust 统一处理 WinRT 异步类型Makepad 仓库中的 windows future用 Rust 统一处理 WinRT 异步类型 windows future 是 Windows 生态下的前端UI组件3D渲染跨平台游戏开发深入理解 Rust 的可恢复错误处理Result 枚举、? 运算符与错误传播实战The Rust Programming Language 官方仓库深度解析深入理解 Rust 的可恢复错误处理 Result 枚举、 ? 运算符与错误传播实战The Rust Programming Language 官方仓库深度教程文档上一篇窗口大小调整工具 Window Resizer3 步强制改好拖不动的窗口下一篇4 步把微博备份成 PDFSpeechless 免费导出上手指南创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考
阅读完成 · 觉得有帮助?