windows-result 深入解析:Makepad 仓库中的 Windows 错误处理核心库
前端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),仅供参考

相关新闻

基于SpringBoot的社区公益活动管理系统的设计与实现-计算机毕设 附源码94420

基于SpringBoot的社区公益活动管理系统的设计与实现-计算机毕设 附源码94420

基于SpringBoot的社区公益活动管理系统第二章 相关技术介绍2.1 Spring BootSpring Boot为企业级Web应用快速搭建提供支持,以约定优于配置的方式组织工程结构,把依赖管理、自动装配、外部化配置等能力集中到统一的启动和运行模型中,使得后端服…

2026/10/9 7:39:14 阅读更多 →
Brython 文件读取实战:open() 与 browser.ajax 双方案详解

Brython 文件读取实战:open() 与 browser.ajax 双方案详解

编程语言语言运行时编译器前端 【免费下载链接】brython Brython (Browser Python) is an implementation of Python 3 running in the browser 项目地址: https://gitcode.com/gh_mirrors/br/brython 点击查看 免费下载 导读 本文基于 Brython 官方 Cookbook 中的…

2026/10/9 7:39:14 阅读更多 →
Duktape 深入解析:Object.defineProperty() 内部算法与 [[DefineOwnProperty]] 实现

Duktape 深入解析:Object.defineProperty() 内部算法与 [[DefineOwnProperty]] 实现

语言运行时嵌入式解释器 【免费下载链接】duktape Duktape - embeddable Javascript engine with a focus on portability and compact footprint 项目地址: https://gitcode.com/gh_mirrors/du/duktape 点击查看 免费下载 导读 Object.defineProperty() 是 ECMAS…

2026/10/9 7:39:14 阅读更多 →

最新新闻

深入剖析ReentrantLock与AQS:从源码看Java并发锁的排队与唤醒机制

深入剖析ReentrantLock与AQS:从源码看Java并发锁的排队与唤醒机制

你可能见过这样的场景:一群人冲进教室,座位只有几个,谁抢到谁坐,抢不到的只能排队等着。Java并发里的ReentrantLock,本质上就是在干这件事。不过它的“排队”不是简单的先来后到,而是一套基于AQS&#xff0…

2026/10/9 8:51:14 阅读更多 →
Windows 10下MySQL 5.5升级5.7:备份迁移避坑指南

Windows 10下MySQL 5.5升级5.7:备份迁移避坑指南

给 Windows 10 上跑了好几年的 MySQL 5.5 做升级,说难不难,说简单也真不简单。我刚帮一台老机器把 MySQL 5.5 完整升级到 5.7,整个过程踩了字符集、SQL 模式、用户权限迁移、服务安装好几个坑,最后整理出了一套可以直接照着做的流…

2026/10/9 8:51:14 阅读更多 →
MySQL怎么查看?详解库表数据与运行状态查看命令

MySQL怎么查看?详解库表数据与运行状态查看命令

前阵子一个刚转行做开发的朋友问我:“MySQL我装上了,也能连上了,可我怎么知道它到底跑没跑?怎么看数据库里有什么表?怎么看某张表有没有数据?”我把这几个问题拆开一聊,发现其实很多人卡住的不是…

2026/10/9 8:51:14 阅读更多 →
Python实战:用CNN卷积神经网络实现图像识别完整流程

Python实战:用CNN卷积神经网络实现图像识别完整流程

图像识别,说白了就是让计算机对着一张图片回答“这是什么”。我最近用Python完整跑了一个CNN卷积神经网络的图像识别项目,从环境安装、数据准备到模型训练、效果调优都捋了一遍,踩的坑不算少。写这篇就是想把整个实战过程拆开讲清楚&#xff…

2026/10/9 8:51:14 阅读更多 →
Servlet+JSP+Bootstrap+MySQL学生信息管理系统实战全解析

Servlet+JSP+Bootstrap+MySQL学生信息管理系统实战全解析

简介:这是一份基于 JavaServletJSPBootstrapMySQL 的学生信息管理系统项目源码,面向正在进行 Java Web 期末大作业、课程设计或毕业设计的本专科学生,也适合初学 Servlet/JSP 分层开发的读者。项目采用 ServletDAOVO 分层结构,涵盖…

2026/10/9 8:51:14 阅读更多 →
空气悬架建模实战:从变刚度原理到控制标定全流程解析

空气悬架建模实战:从变刚度原理到控制标定全流程解析

坐进一台配了空气悬架的车,从一段满是补丁的国道上下来,你大概率会忍不住感叹一句“这底盘是真的舒服”。但这份体感背后并不是玄学,真正让它和普通螺旋弹簧拉开差距的,是空气弹簧本身的变刚度特性。要把这种特性吃透、真正用于产…

2026/10/9 8:50:13 阅读更多 →

日新闻

Java时间API实战:LocalDate、Date与ZonedDateTime的转换与避坑指南

Java时间API实战:LocalDate、Date与ZonedDateTime的转换与避坑指南

Java时间API这个话题,隔三差五就会在群里被翻出来讨论一次。上周还有个同事线上处理一个订单超时问题,排查到最后发现是ZonedDateTime序列化后时区丢了,用户在下单当天晚上看到的时间整整差了8个小时。这类问题几乎每个做Java开发的人都遇到过…

2026/10/9 0:00:49 阅读更多 →
EasyTier实践:从NAT穿透到子网代理的异地组网部署与排错

EasyTier实践:从NAT穿透到子网代理的异地组网部署与排错

前几个月我手头有好几台机器需要互相访问:办公室台式机、家里 NAS、还有一台云主机。如果只是偶尔传个文件倒还好,问题是工作场景经常要在几处环境之间来回切换,每次都先登录跳板机再层层代理,实在折腾。我先后试过端口映射、自建…

2026/10/9 0:00:49 阅读更多 →
AI Agent工程实战:从七要素到七个决策点的系统设计指南

AI Agent工程实战:从七要素到七个决策点的系统设计指南

AI Agent 这个词在过去一年里被反复提及,但真正动手搭过一套能跑起来的 Agent 系统的人都知道,从"知道它是什么"到"让它稳定干活"之间隔着一整套工程决策。我前后参与过几个 Agent 项目的落地,从最初用现成框架拼装&…

2026/10/9 0:01:50 阅读更多 →

周新闻

KT148A语音芯片外挂8002D功放的工程实践指南

KT148A语音芯片外挂8002D功放的工程实践指南

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

2026/10/8 15:26:32 阅读更多 →
LLC谐振变换器增益公式推导:从FHA等效到完整归一化表达式

LLC谐振变换器增益公式推导:从FHA等效到完整归一化表达式

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

2026/10/8 15:26:40 阅读更多 →
ARM架构深度解析:从RISC设计理念到交叉编译实战

ARM架构深度解析:从RISC设计理念到交叉编译实战

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

2026/10/8 10:10:36 阅读更多 →

月新闻

我发现了一个新思路:用 Remotion + Claude Code 像写代码一样自动化生成短视频

我发现了一个新思路:用 Remotion + Claude Code 像写代码一样自动化生成短视频

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

2026/10/8 21:13:17 阅读更多 →
Windows下 Codex 中 Chrome 和 Computer Use 插件不可用问题排查及解决参考方式:TaoToken 统一 Key 配置与验证

Windows下 Codex 中 Chrome 和 Computer Use 插件不可用问题排查及解决参考方式:TaoToken 统一 Key 配置与验证

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

2026/10/8 15:26:17 阅读更多 →
黑夜航拍船只数据集训练YOLOV5模型全流程解析

黑夜航拍船只数据集训练YOLOV5模型全流程解析

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

2026/10/9 6:17:20 阅读更多 →