WSL C API 详解:WslcLoadImageOptions 结构与容器镜像加载进度回调
WSL C API 详解WslcLoadImageOptions 结构与容器镜像加载进度回调【免费下载链接】WSLWindows Subsystem for Linux项目地址: https://gitcode.com/GitHub_Trending/ws/WSL导读WslcLoadImageOptions是 Windows Subsystem for LinuxWSL容器 SDKWSLC SDK中用于配置**本地镜像加载Load Image**操作的可选参数结构体。它本身只承载一个进度回调函数指针及其上下文却贯穿了WslcLoadSessionImage/WslcLoadSessionImageFromFile两个镜像导入 API 的整个执行过程是开发者获取加载进度、实现 UI 进度条的关键入口。读完本文你将掌握该结构的完整定义、回调消息的数据格式、底层桥接实现以及 C 与 WinRT 两种调用方式下的最小可用示例。一、结构定义与字段说明WslcLoadImageOptions定义于 wslcsdk.h完整定义如下typedef struct WslcLoadImageOptions { _In_opt_ WslcContainerImageProgressCallback progressCallback; _In_opt_ PVOID progressCallbackContext; } WslcLoadImageOptions;字段类型说明progressCallbackWslcContainerImageProgressCallback镜像加载进度回调函数指针。_In_opt_表示可选输入参数可传NULLprogressCallbackContextPVOID透传给回调函数的用户自定义上下文指针。_In_opt_同样可选通常指向调用方维护的状态对象用于在回调中区分不同的加载会话两个字段均以_In_opt_标注意味着整个结构体可以“零配置”使用将其初始化为{}或全零即可完成一次不带进度反馈的镜像加载。若希望接收进度则必须同时提供回调函数与上下文二者配合使用。二、在镜像管理 API 中的定位WslcLoadImageOptions属于 WSLC SDK 的IMAGE MANAGEMENT镜像管理模块与它同族的 Options 结构体还包括WslcPullImageOptions——从镜像仓库拉取镜像额外携带uri与registryAuth字段WslcImportImageOptions——从内存句柄或本地文件导入并命名镜像配套imageName参数WslcLoadImageOptions——不加命名、原样装载镜像内容到会话中是本文主题WslcTagImageOptions、WslcPushImageOptions——打标签与推送镜像。其中 Pull / Import / Load / Push 四类操作都共享同一个回调类型见 wslcsdk.htypedef HRESULT(CALLBACK* WslcContainerImageProgressCallback)(const WslcImageProgressMessage* progress, PVOID context);该结构体被以下两个 API 消费见 wslcsdk.hSTDAPI WslcLoadSessionImage( _In_ WslcSession session, _In_ HANDLE imageContent, // 镜像内容的句柄如文件句柄 _In_ uint64_t imageContentBytes, // 镜像内容的字节数 _In_opt_ const WslcLoadImageOptions* options, _Outptr_opt_result_z_ PWSTR* errorMessage); STDAPI WslcLoadSessionImageFromFile( _In_ WslcSession session, _In_z_ PCWSTR path, // 本地镜像文件路径宽字符 _In_opt_ const WslcLoadImageOptions* options, _Outptr_opt_result_z_ PWSTR* errorMessage);两者的差别仅在于镜像内容的提供方式前者直接传入内存/文件句柄与长度后者传入磁盘路径后由 SDK 内部解析文件。options参数对两者而言都是可选的传入NULL亦可。三、回调消息的完整格式当设置了progressCallback后SDK 会通过WslcImageProgressMessage结构向回调汇报加载进度。该消息结构的定义位于 wslcsdk.h由三部分组成typedef struct WslcImageProgressMessage { _Out_ PCSTR id; // 层 ID 或摘要digest _Out_ WslcImageProgressStatus status; // 当前状态 _Out_ WslcImageProgressDetail detail; } WslcImageProgressMessage; typedef struct WslcImageProgressDetail { _Out_ uint64_t currentBytes; // 已处理的字节数 _Out_ uint64_t totalBytes; // 预期总字节数 } WslcImageProgressDetail;status取值来自WslcImageProgressStatus枚举语义与 Docker CLI 的层进度文案一一对应枚举值数值对应引擎文案WSLC_IMAGE_PROGRESS_STATUS_UNKNOWN0无法识别WSLC_IMAGE_PROGRESS_STATUS_PULLING1Pulling fs layerWSLC_IMAGE_PROGRESS_STATUS_WAITING2WaitingWSLC_IMAGE_PROGRESS_STATUS_DOWNLOADING3DownloadingWSLC_IMAGE_PROGRESS_STATUS_VERIFYING4Verifying ChecksumWSLC_IMAGE_PROGRESS_STATUS_EXTRACTING5ExtractingWSLC_IMAGE_PROGRESS_STATUS_COMPLETE6Pull complete详细的字段语义可继续参阅 WslcImageProgressMessage 与 WslcImageProgressDetail 两个参考页。所有镜像相关结构体的完整索引见 structures 索引页。四、底层实现进度消息如何从引擎桥接到回调WslcLoadImageOptions中的回调并非被 SDK 直接调用而是经过一层适配器封装。核心实现在 ProgressCallback.cpp 与 ProgressCallback.h条件创建ProgressCallback::CreateIf模板方法检查options及其progressCallback是否为非空仅在调用方提供回调时才创建适配器对象见 ProgressCallback.h。统一桥接适配器实现IWSLCCompatProgressCallback::OnProgress(LPCSTR Status, LPCSTR Id, ULONGLONG Current, ULONGLONG Total)将引擎下发的字符串状态如Downloading、Extracting通过ConvertStatus映射为WslcImageProgressStatus枚举再组装成WslcImageProgressMessage转发给用户回调见 ProgressCallback.cpp。状态映射表ConvertStatus内部维护了一份引擎文案到枚举的映射含前缀匹配与全等匹配两种策略例如Pulling from 前缀与Pulling fs layer全等均映射为WSLC_IMAGE_PROGRESS_STATUS_PULLING无法识别的状态会记录调试日志并返回UNKNOWN见 ProgressCallback.cpp。源码注释中也明确指出这种基于引擎字符串的映射较为脆弱WSLC 刻意避免将引擎文案本地化以维持映射的稳定性。在 wslcsdk.cpp 中WslcLoadSessionImageImpl展示了完整的调用链static HRESULT WslcLoadSessionImageImpl( WslcSessionImpl* internalSession, const WslcLoadImageOptions* options, ErrorInfoWrapper errorInfoWrapper, const ImageFileResolver imageFile) { auto progressCallback ProgressCallback::CreateIf(options); return errorInfoWrapper.CaptureResult(internalSession-session-LoadImage( wsl::windows::common::apicompat::Convert(ToCOMInputHandle(imageFile.Handle())), progressCallback.get(), imageFile.Length(), nullptr)); }可以看到options在此处仅被用于提取回调加载动作最终落到内部会话的LoadImage方法上而错误则统一通过ErrorInfoWrapper转出为errorMessage字符串。这也解释了为什么WslcLoadSessionImage/WslcLoadSessionImageFromFile都要求session必须先处于有效状态——源码在进入实现前会执行RETURN_HR_IF_NULL(HRESULT_FROM_WIN32(ERROR_INVALID_STATE), internalType-session)校验。五、实战示例5.1 C 语言最小用法不关心进度PWSTR errorMessage nullptr; HRESULT hr WslcLoadSessionImageFromFile( session, LC:\\images\\mycontainer.tar, nullptr, // 不传 options 即可跳过进度回调 errorMessage); if (FAILED(hr)) { // errorMessage 中携带可读的错误描述 // 使用后调用 CoTaskMemFree(errorMessage) 释放 }5.2 C 语言带进度回调struct LoadContext { HWND hwnd; // 用于更新 UI 进度条 }; HRESULT CALLBACK OnLoadProgress(const WslcImageProgressMessage* progress, PVOID context) noexcept { auto* ctx static_castLoadContext*(context); if (progress ctx) { if (progress-status WSLC_IMAGE_PROGRESS_STATUS_DOWNLOADING || progress-status WSLC_IMAGE_PROGRESS_STATUS_EXTRACTING) { uint64_t current progress-detail.currentBytes; uint64_t total progress-detail.totalBytes; // 计算百分比并刷新 UI…… } } return S_OK; } WslcLoadImageOptions options{}; options.progressCallback OnLoadProgress; options.progressCallbackContext ctx; PWSTR errorMessage nullptr; HRESULT hr WslcLoadSessionImage( session, imageHandle, imageSizeBytes, options, errorMessage);需要注意WslcImageProgressMessage是 SDK 内部栈上构造的临时结构见 ProgressCallback.cpp回调函数不能保存该指针越过本次调用如需保留数据应自行拷贝回调的返回值HRESULT会被 SDK 采纳非成功返回值可影响加载流程建议始终返回S_OK。5.3 WinRT 包装LoadImageAsync 的进度透传在 C/WinRT 层面winrt/Session.cpp 的LoadImageAsync演示了官方如何消费本结构体它先构造WslcLoadImageOptions再将progressCallback设为内部静态函数ImageProgressCallback并把progressCallbackContext指向 WinRT 进度令牌助手ProgressCallbackHelper当 SDK 回调触发时内部函数把WslcImageProgressMessage包装成 WinRT 的ImageProgress对象并通过IAsyncActionWithProgress上报最终映射到调用方的进度委托如ProgressT。无进度需求的同步版本LoadImage则直接使用零初始化结构体见 winrt/Session.cpp。因此在 C#/C/WinRT 侧只需var progress new ProgressImageProgress(p { // p.Status / p.CurrentBytes / p.TotalBytes }); await session.LoadImageAsync(C:\images\mycontainer.tar).AsTask(progress);即可获得与 C API 等价的进度信息无需手动接触WslcLoadImageOptions。六、注意事项与最佳实践所有字段均可省略progressCallback与progressCallbackContext均为_In_opt_传入零初始化结构体即可完成加载追求进度体验时才需要配置回调。回调与上下文必须配对只设置回调而不设置上下文回调仍会被调用context为NULL但实现中应自行判空推荐始终用上下文携带 UI 状态或会话标识。会话状态校验两个 Load API 在入口处都会检查内部会话有效性无效时返回HRESULT_FROM_WIN32(ERROR_INVALID_STATE)见 wslcsdk.cpp调用前应确保会话已创建成功。错误信息释放失败时errorMessage由 SDK 分配调用方需使用CoTaskMemFree释放WslcLoadSessionImageFromFile中的路径参数为PCWSTR宽字符与WslcImportSessionImageFromFile的imageNamePCSTR不同注意字符集差异。回调生命周期若加载为同步 API回调只在函数执行期间触发若为异步如 WinRTLoadImageAsync需保证上下文对象在异步操作完成前存活——这正是 winrt/Session.cpp 中通过get_strong()保持会话存活的原因。综上WslcLoadImageOptions虽小却是 WSLC 镜像加载链路中连接“引擎进度”与“应用 UI”的枢纽理解它的字段语义、消息格式与桥接实现即可在任意支持 WSLC SDK 的宿主应用中稳定地实现容器镜像加载的进度反馈。【免费下载链接】WSLWindows Subsystem for Linux项目地址: https://gitcode.com/GitHub_Trending/ws/WSL创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考