ARTICLE DETAIL

资讯详情

深耕网站建设与运营推广的一线实战洞察。

WSL 容器 C API 端到端实战:用 WslcSDK 驱动容器完整生命周期

WSL 容器 C API 端到端实战:用 WslcSDK 驱动容器完整生命周期 WSL 容器 C API 端到端实战用 WslcSDK 驱动容器完整生命周期【免费下载链接】WSLWindows Subsystem for Linux项目地址: https://gitcode.com/GitHub_Trending/ws/WSLWSL 容器WSLC在 Windows Subsystem for Linux 项目中提供了一套面向开发者的 C API——WslcSDK让原生 C/C 程序能够以编程方式创建会话、拉取镜像、启动容器并管理其中的 Linux 进程。本文以仓库中的 End-to-End Example 为骨架逐阶段拆解一个完整生命周期示例并结合 wslcsdk.h 头文件、wslcsdk.cpp 实现与仓库内示例代码带你掌握从环境检查、会话管理、镜像拉取到容器启停清理的完整开发链路读完即可独立编写自己的第一个 WSL 容器控制程序。一、WslcSDK C API 概览WSL 容器 API 对外暴露为一套扁平 C 接口相关定义全部集中在公共头文件 wslcsdk.h 中编译时链接wslcsdk.lib、运行时依赖wslcsdk.dll。整套 API 按职责分为以下几组详见 C API 参考索引API 分组典型接口职责Session APIsWslcInitSessionSettings、WslcCreateSession、WslcTerminateSession会话的初始化、创建、终止与释放Container APIsWslcInitContainerSettings、WslcCreateContainer、WslcStartContainer容器的定义、创建、启动、检查、停止与删除Process APIsWslcInitProcessSettings、WslcCreateContainerProcess、WslcGetProcessExitCode容器内进程的配置、创建与状态查询Image APIsWslcPullSessionImage、WslcListSessionImages、WslcDeleteSessionImage容器镜像的拉取、导入、加载、打标签、推送、枚举与删除Storage APIsWslcCreateSessionVhdVolume、WslcDeleteSessionVhdVolume基于 VHD 的会话卷存储管理Install Version APIsWslcGetMissingComponents、WslcGetVersion、WslcInstallWithDependencies平台组件检查、安装与版本查询值得注意的是该 API 目前处于预览阶段。头文件开头的 PREVIEW NOTICE 明确声明API 可能在未来版本中不经预告地发生破坏性变更不建议在正式生产环境中依赖其稳定性见 wslcsdk.h。二、生命周期全景端到端示例的九个阶段原文档 end-to-end-example.md 用一段完整main()展示了 WSL 容器的全生命周期共九个阶段初始化会话设置Session Settings创建会话Create Session拉取镜像Pull Image配置容器Configure Container创建并启动容器Create Start Container检查容器状态 / 等待 init 进程退出Inspect创建第二个进程Create Second Process停止并删除容器Stop Delete Container释放句柄并终止会话Release Terminate下文将按这九个阶段逐层深入每一阶段都同时给出怎么用与为什么并在最后附上完整可编译源码。三、环境准备与前置检查任何 WSLC 程序的第一步都是初始化 COM 运行库。示例中调用CoInitializeEx(nullptr, COINIT_MULTITHREADED);由于WslcSDK内部依赖 COM 对象与CoTaskMemAlloc分配的错误消息所有使用 WslcSDK 的线程都必须先初始化 COM程序退出前再以CoUninitialize()收尾。随后进行两项前置检查WslcComponentFlags missing WSLC_COMPONENT_FLAG_NONE; hr WslcGetMissingComponents(missing); if (FAILED(hr) || missing ! WSLC_COMPONENT_FLAG_NONE) { printf(WSL components are missing. Run: wsl --install\n); CoUninitialize(); return 1; } WslcVersion ver {}; WslcGetVersion(ver); printf(WSL version: %u.%u.%u\n, ver.major, ver.minor, ver.revision);WslcGetMissingComponents返回位标志WslcComponentFlags定义见 wslcsdk.h表示当前机器缺失的组件WSLC_COMPONENT_FLAG_NONE (0)无缺失一切就绪WSLC_COMPONENT_FLAG_VIRTUAL_MACHINE_PLATFORM (1)缺少虚拟机平台可选功能安装该组件需要重启WSLC_COMPONENT_FLAG_WSL_PACKAGE (2)WSL 运行时包版本过低无法提供 WSLC 支持WSLC_COMPONENT_FLAG_SDK_NEEDS_UPDATE (4)WSLC SDK 自身需要更新。若missing非零示例直接提示用户运行wsl --install并退出。WslcGetVersion则把 SDK 版本写入WslcVersion结构体major/minor/revision三个字段见 wslcsdk.h用于向用户展示或做版本判断。除检查外SDK 还提供WslcInstallWithDependencies以编程方式补齐缺失组件支持WSLC_INSTALL_OPTION_REPAIR重装模式并可通过WslcInstallCallback回调获得安装进度。四、会话的初始化与创建会话Session是 WSLC 一切操作的顶层容器镜像、容器、卷都隶属于某个会话。第一步是用WslcInitSessionSettings填写会话设置std::filesystem::path storagePath std::filesystem::current_path(); WslcSessionSettings sessionSettings; hr WslcInitSessionSettings(LMyApp, storagePath.c_str(), sessionSettings); if (FAILED(hr)) return 1;按 wslcinitsessionsettings.md 的说明该函数接收两个关键参数namePCWSTR会话名称。它既是显示名也是机器级的会话唯一键——若同名会话已存在创建会以ERROR_ALREADY_EXISTS失败storagePathPCWSTR会话存储目录路径不存在时会被自动创建。需要特别警惕的是会话名称的安全语义同一台机器上的所有用户都能看到会话的名称、创建者 SID 和创建进程 PID。因此切勿把凭据或其他敏感信息放进会话名中。初始化之后可以按需定制资源配额。示例中为会话分配了 4 个 CPU 与 4 GB 内存WslcSetSessionSettingsCpuCount(sessionSettings, 4); WslcSetSessionSettingsMemory(sessionSettings, 4096);会话的可选设置远不止这两项全部见 wslcsdk.h接口含义WslcSetSessionSettingsCpuCount会话可用的 CPU 数量uint32_tWslcSetSessionSettingsMemory会话内存上限单位 MBWslcSetSessionSettingsTimeout会话超时单位毫秒WslcSetSessionSettingsVhd指定会话主卷 VHD 需求WslcVhdRequirements名称、大小、类型WslcSetSessionSettingsFeatureFlags会话特性位如WSLC_SESSION_FEATURE_FLAG_ENABLE_GPU其中 VHD 需求结构体WslcVhdRequirements的name与sizeBytes会被WslcSetSessionSettingsVhd使用而flags/uid/gid字段仅由存储 APIWslcCreateSessionVhdVolume解释传给WslcSetSessionSettingsVhd的非零标志会以E_INVALIDARG被拒绝见 wslcsdk.h。VHD 类型WslcVhdType支持WSLC_VHD_TYPE_DYNAMIC动态扩展默认与WSLC_VHD_TYPE_FIXED固定分配。设置就绪后创建会话WslcSession session nullptr; hr WslcCreateSession(sessionSettings, session, error); if (FAILED(hr)) { wprintf(LSession creation failed: %s\n, error ? error : Lunknown); CoTaskMemFree(error); CoUninitialize(); return 1; }WslcCreateSession输出一个不透明的WslcSession句柄由DECLARE_HANDLE声明见 wslcsdk.h。出错时可通过第三个参数拿到人类可读的错误消息字符串——它由CoTaskMemAlloc分配调用方必须用CoTaskMemFree释放这是整个 SDK 统一的资源约定。示例对每处失败分支都做了打印错误 → 释放 error → 退出的处理这是 WSLC 编程的推荐范式。五、拉取容器镜像会话创建后示例从 Docker Hub 拉取 Alpine Linux 镜像WslcPullImageOptions pullOpts {}; pullOpts.uri docker.io/library/alpine:latest; hr WslcPullSessionImage(session, pullOpts, error); if (FAILED(hr)) { wprintf(LPull failed: %s\n, error ? error : Lunknown); CoTaskMemFree(error); WslcTerminateSession(session); WslcReleaseSession(session); CoUninitialize(); return 1; }WslcPullImageOptions结构体见 wslcsdk.h包含四个字段uri镜像地址示例使用docker.io/library/alpine:latest即 Docker Hub 上的官方 Alpine 镜像progressCallback/progressCallbackContext拉取进度回调及其上下文registryAuth私有仓库认证串Base64 编码的X-Registry-Auth头值公共镜像可留空。进度回调以WslcImageProgressMessage为入参其status字段完整覆盖了拉取的各个阶段PULLING拉取层、WAITING等待、DOWNLOADING下载中、VERIFYING校验、EXTRACTING解压、COMPLETE完成detail中携带currentBytes/totalBytes便于绘制下载进度条见 wslcsdk.h。关于进度回调的完整用法可参考 wslcpullsessionimage.md 中的示例。镜像 API 还支持离线场景WslcImportSessionImage/WslcImportSessionImageFromFile从句柄或文件导入、WslcLoadSessionImage/WslcLoadSessionImageFromFile从文件加载、WslcTagSessionImage打标签、WslcPushSessionImage推送、WslcListSessionImages枚举与WslcDeleteSessionImage删除。访问私有仓库时可用WslcSessionAuthenticate先换取身份令牌服务端返回 token 时产出{identitytoken: ...}否则回退为{username: ..., password: ...}两者都编码为 Base64 JSON可直接作为registryAuth使用见 wslcsdk.h。六、配置 init 进程与容器镜像拉取完成后示例配置容器的 init 进程容器启动后第一个执行的进程WslcProcessSettings initProcSettings; WslcInitProcessSettings(initProcSettings); PCSTR argv[] { /bin/echo, Hello from WSL Container! }; WslcSetProcessSettingsCmdLine(initProcSettings, argv, 2);WslcInitProcessSettings将WslcProcessSettings结构体清零初始化然后WslcSetProcessSettingsCmdLine用标准 C 风格的argv数组PCSTR const* 参数个数size_t指定命令行。进程设置还可通过 process-apis 下的一组接口进一步定制接口含义WslcSetProcessSettingsWorkingDirectory进程工作目录容器内绝对路径WslcSetProcessSettingsCmdLine命令行参数数组WslcSetProcessSettingsEnvVariables环境变量keyvalue数组WslcSetProcessSettingsCallbacks注册 stdout/stderr 数据回调与进程退出回调接着配置容器本体WslcContainerSettings containerSettings; WslcInitContainerSettings(alpine:latest, containerSettings); WslcSetContainerSettingsName(containerSettings, hello-container); WslcSetContainerSettingsInitProcess(containerSettings, initProcSettings);WslcInitContainerSettings以镜像名alpine:latest与拉取时的镜像对应初始化WslcContainerSettings。可选的容器设置接口相当丰富见 wslcsdk.h接口含义WslcSetContainerSettingsName容器名称WslcSetContainerSettingsInitProcess指定 init 进程设置WslcSetContainerSettingsNetworkingMode网络模式WSLC_CONTAINER_NETWORKING_MODE_NONE隔离或WSLC_CONTAINER_NETWORKING_MODE_BRIDGED桥接底层映射为bridgeWslcSetContainerSettingsHostName/WslcSetContainerSettingsDomainName容器主机名与域名WslcSetContainerSettingsFlags容器标志见下WslcSetContainerSettingsPortMappings端口映射数组Windows 端口 ↔ 容器端口TCP/UDP可指定绑定地址WslcSetContainerSettingsVolumes绑定卷数组Windows 路径 ↔ 容器路径可只读WslcSetContainerSettingsNamedVolumes命名卷数组引用会话 VHD 卷容器标志WslcContainerFlags支持WSLC_CONTAINER_FLAG_AUTO_REMOVE停止后自动删除、WSLC_CONTAINER_FLAG_ENABLE_GPU启用 GPU与WSLC_CONTAINER_FLAG_PRIVILEGED特权模式。端口映射WslcContainerPortMapping的windowsAddress字段可覆盖默认绑定地址同时接受 IPv4/IPv6 的sockaddr_storage。七、创建并启动容器配置完成后创建容器句柄WslcContainer container nullptr; hr WslcCreateContainer(session, containerSettings, container, error);WslcCreateContainer接收会话句柄与容器设置输出WslcContainer句柄。随后启动hr WslcStartContainer(container, WSLC_CONTAINER_START_FLAG_NONE, error);WslcStartContainer的第二个参数是启动标志见 wslcsdk.hWSLC_CONTAINER_START_FLAG_NONE (0)普通启动WSLC_CONTAINER_START_FLAG_ATTACH (1)附加模式配合WslcSetContainerInitProcessIOCallbacks可将 init 进程的 stdout/stderr 直接接到 Windows 侧。启动失败时示例执行了一套完整的回滚清理WslcDeleteContainer(container, WSLC_DELETE_CONTAINER_FLAG_FORCE, nullptr); WslcReleaseContainer(container); WslcTerminateSession(session); WslcReleaseSession(session); CoUninitialize();这套失败即全量回收的顺序值得注意先删容器、再释放容器句柄、再终止并释放会话、最后反初始化 COM保证任何路径下都不会泄漏句柄。八、等待 init 进程退出并读取退出码原文档概述中的第 6 步是检查容器对应示例代码中获取 init 进程句柄并等待其退出的逻辑如需获取真正的结构化检查数据可调用WslcInspectContainer其返回的 ANSI 字符串同样由CoTaskMemAlloc分配、需调用方CoTaskMemFree释放见 wslcsdk.hWslcProcess initProc nullptr; hr WslcGetContainerInitProcess(container, initProc); if (SUCCEEDED(hr)) { HANDLE exitEvent nullptr; if (SUCCEEDED(WslcGetProcessExitEvent(initProc, exitEvent))) { WaitForSingleObject(exitEvent, 30000); // 30-second timeout } INT32 exitCode 0; if (SUCCEEDED(WslcGetProcessExitCode(initProc, exitCode))) { printf(Process exited with code: %d\n, exitCode); } WslcReleaseProcess(initProc); }这套等待机制非常典型WslcGetContainerInitProcess取出容器的 init 进程句柄WslcProcessWslcGetProcessExitEvent获取进程退出事件HANDLE交给WaitForSingleObject阻塞等待——示例设置了 30 秒超时WslcGetProcessExitCode读取退出码WslcReleaseProcess释放进程句柄。进程状态还可通过WslcGetProcessState查询RUNNING/EXITED/SIGNALLED/UNKNOWN或通过WslcGetProcessPid拿到容器内 Linux PID通过WslcGetProcessIOHandle拿到 stdin/stdout/stderr 句柄做手动 IO 重定向。此外WslcSignalProcess可向进程发送 POSIX 信号信号枚举WslcSignal覆盖了SIGHUP(1)、SIGINT(2)、SIGQUIT(3)、SIGKILL(9)、SIGTERM(15)见 wslcsdk.h。九、在运行中的容器里创建第二个进程原文档概述的第 7 步是创建第二个进程。在 WSLC 中向已运行的容器再投递进程的接口是WslcCreateContainerProcess见 wslcsdk.hSTDAPI WslcCreateContainerProcess( _In_ WslcContainer container, _In_ WslcProcessSettings* newProcessSettings, _Out_ WslcProcess* newProcess, _Outptr_opt_result_z_ PWSTR* errorMessage);即容器内执行exec语义传入一份新的WslcProcessSettings得到新的WslcProcess句柄。仓库中的 WSLC-HelloWorld 示例完整演示了这一用法——容器 init 进程是/bin/sleep 60保持容器存活随后用WslcCreateContainerProcess创建/bin/echo进程并通过回调方式把输出流回 Windows 控制台见 helloworld.c。该示例同时展示了进程回调的正确姿势在WslcProcessCallbacks中注册onStdOut、onStdErr与onExit其中onExit在进程退出且 IO 全部刷出后触发可避免退出与 IO 缓冲刷新之间的竞态。头文件明确提示使用回调会占用 IO 句柄之后无法再通过WslcGetProcessIOHandle获取句柄见 wslcsdk.h。十、停止、删除与全量释放示例收尾阶段先查询容器状态若仍在运行则发送信号停止WslcContainerState containerState WSLC_CONTAINER_STATE_INVALID; if (SUCCEEDED(WslcGetContainerState(container, containerState)) containerState WSLC_CONTAINER_STATE_RUNNING) { WslcStopContainer(container, WSLC_SIGNAL_SIGTERM, 10, nullptr); } WslcDeleteContainer(container, WSLC_DELETE_CONTAINER_FLAG_NONE, nullptr); WslcReleaseContainer(container); WslcTerminateSession(session); WslcReleaseSession(session); CoUninitialize(); return 0;逐行拆解这段安全关停状态查询WslcGetContainerState返回WslcContainerState枚举取值包括INVALID、CREATED、RUNNING、EXITED、DELETED见 wslcsdk.h。只有确认是RUNNING才发送停止信号避免重复停止。优雅停止WslcStopContainer(container, WSLC_SIGNAL_SIGTERM, 10, nullptr)发送SIGTERM并给出 10 秒宽限期若需要立即终止可改用WSLC_SIGNAL_SIGKILL。删除容器WslcDeleteContainer的 flags 支持WSLC_DELETE_CONTAINER_FLAG_NONE与WSLC_DELETE_CONTAINER_FLAG_FORCE强制删除即使容器仍在运行。释放句柄WslcReleaseContainer释放容器句柄。终止并释放会话WslcTerminateSession终止会话底层停止相关 VMWslcReleaseSession释放会话句柄。WslcSession是引用计数式的 COM 对象WslcTerminateSession与WslcReleaseSession是两个独立职责前者关停会话运行实体后者归还句柄引用。若想让会话在崩溃时被感知可注册WslcRegisterSessionCrashDumpCallback获取 Linux 侧崩溃转储回调并通过WslcGetSessionTerminationEvent/WslcGetSessionTerminationReason区分正常关停SHUTDOWN与崩溃CRASHED。十一、错误处理与内存管理规范WSLC 全 API 采用HRESULT返回值绝大多数带errorMessagePWSTR*出参其管理遵循三条铁律错误字符串必须释放errorMessage由CoTaskMemAlloc分配调用方有义务用CoTaskMemFree释放NULL 检查兜底失败时error可能为空指针示例统一使用error ? error : Lunknown的三元表达式兜底先释放再退出任何失败分支都需按容器 → 会话 → COM的顺序完成清理示例中 pull、create、start 三个失败分支都做了完整的反向回收。SDK 定义了从0x80040601起始的专用错误码族WSLC_E_*共 19 个见 error-codes.md常见的有错误码Hex场景WSLC_E_IMAGE_NOT_FOUND0x80040601镜像不存在WSLC_E_CONTAINER_PREFIX_AMBIGUOUS0x80040602容器 ID 前缀匹配到多个容器WSLC_E_CONTAINER_NOT_FOUND0x80040603容器不存在WSLC_E_CONTAINER_NOT_RUNNING0x80040605容器未在运行WSLC_E_CONTAINER_IS_RUNNING0x80040606容器正在运行删除/操作被拒WSLC_E_SDK_UPDATE_NEEDED0x8004060BSDK 需要更新这些宏以WSLC_E_BASE (0x0600)为起点经MAKE_HRESULT(SEVERITY_ERROR, FACILITY_ITF, ...)生成见 wslcsdk.h与头文件和 IDL 文件保持同步更新。在底层实现上wslcsdk.cppSDK 通过一组FlagsTraits模板与static_assert把公开的Wslc*Flags枚举翻译为内部WSLC*Flags运行时值确保公开值与运行时值永不失配见 wslcsdk.cppWslcSignal与WslcContainerNetworkingMode也通过显式switch完成翻译未知取值直接抛出E_INVALIDARG见 wslcsdk.cpp。此外WslcSessionSettings、WslcContainerSettings、WslcProcessSettings都是定长的不透明结构体分别 72 / 104 / 72 字节8 字节对齐见 constants.md应用层只能通过 setter 接口修改内部实现因此可自由演进而不破坏二进制兼容——这也解释了为什么所有设置都必须先用WslcInit*Settings初始化再逐个 setter 修改。十二、完整端到端示例源码以下为原文档 end-to-end-example.md 的完整示例覆盖从 COM 初始化到会话释放的全部九个阶段#include winsock2.h #include windows.h #include stdio.h #include objbase.h #include filesystem #include wslcsdk.h #pragma comment(lib, ole32.lib) #pragma comment(lib, wslcsdk.lib) int main() { // Initialize COM CoInitializeEx(nullptr, COINIT_MULTITHREADED); HRESULT hr; PWSTR error nullptr; // 0. Check prerequisites WslcComponentFlags missing WSLC_COMPONENT_FLAG_NONE; hr WslcGetMissingComponents(missing); if (FAILED(hr) || missing ! WSLC_COMPONENT_FLAG_NONE) { printf(WSL components are missing. Run: wsl --install\n); CoUninitialize(); return 1; } WslcVersion ver {}; WslcGetVersion(ver); printf(WSL version: %u.%u.%u\n, ver.major, ver.minor, ver.revision); // 1. Initialize and create a session std::filesystem::path storagePath std::filesystem::current_path(); WslcSessionSettings sessionSettings; hr WslcInitSessionSettings(LMyApp, storagePath.c_str(), sessionSettings); if (FAILED(hr)) return 1; // Optionally customize resources WslcSetSessionSettingsCpuCount(sessionSettings, 4); WslcSetSessionSettingsMemory(sessionSettings, 4096); WslcSession session nullptr; hr WslcCreateSession(sessionSettings, session, error); if (FAILED(hr)) { wprintf(LSession creation failed: %s\n, error ? error : Lunknown); CoTaskMemFree(error); CoUninitialize(); return 1; } // 2. Pull an image WslcPullImageOptions pullOpts {}; pullOpts.uri docker.io/library/alpine:latest; hr WslcPullSessionImage(session, pullOpts, error); if (FAILED(hr)) { wprintf(LPull failed: %s\n, error ? error : Lunknown); CoTaskMemFree(error); WslcTerminateSession(session); WslcReleaseSession(session); CoUninitialize(); return 1; } // 3. Configure an init process WslcProcessSettings initProcSettings; WslcInitProcessSettings(initProcSettings); PCSTR argv[] { /bin/echo, Hello from WSL Container! }; WslcSetProcessSettingsCmdLine(initProcSettings, argv, 2); // 4. Configure and create a container WslcContainerSettings containerSettings; WslcInitContainerSettings(alpine:latest, containerSettings); WslcSetContainerSettingsName(containerSettings, hello-container); WslcSetContainerSettingsInitProcess(containerSettings, initProcSettings); WslcContainer container nullptr; hr WslcCreateContainer(session, containerSettings, container, error); if (FAILED(hr)) { wprintf(LContainer creation failed: %s\n, error ? error : Lunknown); CoTaskMemFree(error); WslcTerminateSession(session); WslcReleaseSession(session); CoUninitialize(); return 1; } // 5. Start the container hr WslcStartContainer(container, WSLC_CONTAINER_START_FLAG_NONE, error); if (FAILED(hr)) { wprintf(LStart failed: %s\n, error ? error : Lunknown); CoTaskMemFree(error); WslcDeleteContainer(container, WSLC_DELETE_CONTAINER_FLAG_FORCE, nullptr); WslcReleaseContainer(container); WslcTerminateSession(session); WslcReleaseSession(session); CoUninitialize(); return 1; } // 6. Wait for the init process to exit WslcProcess initProc nullptr; hr WslcGetContainerInitProcess(container, initProc); if (SUCCEEDED(hr)) { HANDLE exitEvent nullptr; if (SUCCEEDED(WslcGetProcessExitEvent(initProc, exitEvent))) { WaitForSingleObject(exitEvent, 30000); // 30-second timeout } INT32 exitCode 0; if (SUCCEEDED(WslcGetProcessExitCode(initProc, exitCode))) { printf(Process exited with code: %d\n, exitCode); } WslcReleaseProcess(initProc); } // 7. Clean up WslcContainerState containerState WSLC_CONTAINER_STATE_INVALID; if (SUCCEEDED(WslcGetContainerState(container, containerState)) containerState WSLC_CONTAINER_STATE_RUNNING) { WslcStopContainer(container, WSLC_SIGNAL_SIGTERM, 10, nullptr); } WslcDeleteContainer(container, WSLC_DELETE_CONTAINER_FLAG_NONE, nullptr); WslcReleaseContainer(container); WslcTerminateSession(session); WslcReleaseSession(session); CoUninitialize(); return 0; }注意/bin/echo执行完毕后 init 进程会立即退出容器状态转为EXITED因此清理阶段的WslcGetContainerState检查通常不会命中RUNNING分支——该检查的真正价值在于通用化当 init 进程是/bin/sleep这类长驻进程时确保容器能被优雅关停。十三、从示例走向真实工程端到端示例解决了生命周期怎么走的问题而仓库内还有两处可直接借鉴的进阶素材WSLC-HelloWorld完整可编译的最小示例helloworld.c。它用WslcSetProcessSettingsCallbacks以回调方式把容器 stdout/stderr 实时转发到 Windows 控制台用WSLC_CONTAINER_FLAG_AUTO_REMOVE让容器停止后自动清理并在wmain中演示了完整的goto cleanup错误回收范式WSLC-Neofetch基于 C 的进阶示例演示在容器内运行neofetch并把终端输出回显到 Windows 侧的完整工程化写法。若你的宿主程序不是 C/CWslcSDK 还提供了 C# 与 WinRT 封装见 WslcSDK/csharp 与 WslcSDK/winrt接口语义与本例的 C 接口一一对应。编写生产级程序时建议结合 session-apis、container-apis、process-apis、image-apis、storage-apis、enumerations 与 error-codes 各参考页逐项核对签名与语义并留意 not-yet-implemented-apis.md 中尚未实现的接口清单避免在预览期依赖尚未落地的能力。【免费下载链接】WSLWindows Subsystem for Linux项目地址: https://gitcode.com/GitHub_Trending/ws/WSL创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考
返回列表