# C# NativeAOT 插件迁移 迁移起始记录:2026-10-23(`0.5.0-dev`);旧代码清理与ABI复验:2026-10-24(`0.5.13-dev`)。 插件业务实现已从 `native/XFEEDPlugin` 迁到 `native/ManagedPlugin`,使用 .NET 10 NativeAOT 输出 Windows x64 DLL。保留原 DLL 名称、C ABI 导出和命名管道协议;此次迁移包含插件内部实现。 ## 源码与产物 | 原实现 | 当前 C# 实现 | | --- | --- | | `plugin.cpp`、`Diagnostics.h` | `PluginLoader.cs`:System32 DirectInput 转发、插件状态、显式观测启动、停用及有限日志 | | `Interaction.cpp` | `InteractionRuntime.cs`:游戏线程采样、历史帧、收放输入、期限与回执 | | `Navigation.cpp` | `Navigation.State/Observation/Fsd/Protocol/Lifecycle.cs`:身份、健康、控制租约、玩家接管、FSD、热量、目标及航路 | | `LocalFlight.inl` | `Navigation.LocalFlight.cs`:星系内目标、观测、输入、原生动作及驾驶权交还 | | `CommerceRead/CommerceTrade/StationServices.inl` | 对应 C# 文件:市场、库存、交易防重、维护、补给与服务回执 | | `GalaxyCatalog/SkyboxCapture.inl` | 对应 C# 文件:星系查询、区域分页、银河概览及 D3D11 天空盒读取 | | `SessionMenu.inl` | `Navigation.SessionMenu.cs`:原菜单观测、动作与会话租约 | | 几何、运动、吸油、热量归一化与原自测 | 对应 C# 文件及 `Navigation.SelfTests.cs` | 2026-10-25 起,客户端以项目引用依赖 `Bundle/Bundle.csproj`,后者引用 `Loader`、`Interaction`、`SessionRecovery`、`CruiseControl` 四个生产模块;它们共同引用 `Platform/Platform.csproj`。平台项目按源码与头文件增量生成配置独立的静态库,NativeAOT 在项目构建内自动生成原生 DLL。`Standalone` 保留为独立诊断项目。 `Bundle/NativeSupport.targets` 在中间目录生成与当次 DLL 匹配的版本和 SHA-256 清单,将四个模块及清单作为八项资源嵌入 `XFEEDToolBox.NativeSupport.dll`。客户端不再复制 `XFEEDToolBox/PluginPackage` 中的预制文件。直接构建或发布客户端即可完成整个依赖图,无需提前运行插件打包脚本。 运行时 `NativeSupportPackage` 把内嵌文件校验并释放到 `%LOCALAPPDATA%/XFEstudio/XFEEDToolBox/native-support/<内容哈希>`;不同版本各用独立目录,缺失或损坏缓存会从当前内嵌资源恢复。游戏插件安装、按需模块加载继续使用原有清单和哈希校验。 2026-10-24已删除 `native/XFEEDPlugin` 下的旧 C++ 业务实现、配套内联文件、版本头和旧探针。历史实现可从 Git 查看;当前源码不保留两套驱动。原27个导出冻结在 `native/ManagedPlugin/abi-exports.json`,验收直接以此清单检查实际AOT DLL,不再读取旧C++源码。 ## 必要的原生边界 `Platform/Boundary.cpp`、`Platform/Invoke.asm` 及既有第三方 MinHook 仅负责内存访问、Windows x64 调用、SEH、指令重定位、寄存器保留与展开信息,不包含游戏偏移或业务规则。该边界静态链接入 AOT DLL,无需额外部署运行时 DLL。 迁移验收发现:位于 AOT 模块中的直接内存访问违例不能依靠原 `__try` 继续执行。安全复制因此使用 `ReadProcessMemory` 的系统边界;游戏函数及动态原子指令通过带 SEH 的调用桥执行。测试覆盖不可访问页读、写、原子操作,以及故障后的再次成功调用。 NativeAOT DLL 保留到宿主进程结束,停用只停止功能和撤销租约,继续使用原管理器的退出后清理流程,不执行 `FreeLibrary`。参见 [Microsoft 的 NativeAOT 库生命周期限制](https://learn.microsoft.com/en-us/dotnet/core/deploying/native-aot/libraries)。 ## 兼容约束 - 原有 27 个 C ABI 导出全部保留,独立验收模块另有商业和接口协议自测。 - 保留 Plugin 的 3 种文本命令、Navigation 的 42 种 JSON 操作及 Interaction 的 3 种操作,schema 仍为 1。 - 保留同一用户 SID、本机限定、消息模式、一次连接一次请求、原读取上限与回复排空。 - 保留 64 位地址字符串、Unicode、字段及错误文本;非有限遥测数值按原 JSON 实现输出 `null`。 - 保留游戏 EXE SHA-256、前导指令检查、所属线程、实体/组件/坐标系/sequence 校验、200/300 ms 期限、owner、generation、取消和重复订单处理。 - 保留原先关闭的能力。`supportsTrade=false`;重进能力仍取决于实际菜单接口就绪状态;未接通的本地超巡、空管和降落能力不会因迁移自动启用。 - `DirectInput8Create` 先执行系统接口,再启动伴随服务;伴随功能失败保持原 HRESULT、输出和 last error。 ## 构建与复验 需要 .NET 10 SDK、Windows SDK 和 Visual Studio x64 工具链;C++ 工具链仍用于必要边界与 NativeAOT 链接。 ```powershell pwsh -File scripts/Build-Plugin.ps1 pwsh -File scripts/Test-ManagedPlugin.ps1 pwsh -File scripts/Build.ps1 pwsh -File scripts/Test.ps1 ``` `Test-ManagedPlugin.ps1 -SkipBuild` 复用已有插件,重新生成隔离边界验证 DLL。验收程序只加载自己的 DLL、分配自己的内存,不连接或注入真实游戏,不卸载 AOT DLL。 以下为0.5.0迁移时的历史验收;后续游戏实测见 [CG跑商实测](CG-TRADING-VALIDATION.md)。0.5.13删除旧源码后的隔离构建、656次原生自测及原27项ABI导出复验通过。 | 迁移时检查 | 结果与证据 | | --- | --- | | 完整 Release 解决方案 | 0 警告、0 错误;`artifacts/managed-solution-build.log` | | 客户端回归 | 552 通过、0 失败、6 个显式集成测试默认跳过;`artifacts/tests-csharp-interfaces-final/test-results.json` | | 真实 AOT 导出、原 ABI、x64 原生 PE、不匹配构建拒绝 | 通过;`artifacts/managed-plugin-validation.json` | | 原 21 组自测及商业、接口协议自测 | 23 组 × 8 次 = 184 次通过 | | 内存、整数/浮点/混合参数、12 参数栈、故障恢复及交互 Hook 透明性 | 2 组 × 8 次 = 16 次通过;同一份验证报告 | | System32 DirectInput 对照 | 成功与无效版本的 HRESULT、输出存在性及 last error 均一致 | | 插件管道与停用 | 20 次状态查询,以及显式观测拒绝、停用、停用后查询通过;`artifacts/managed-plugin-handshake/result.json` | 0.5.0迁移当时尚未重验实际飞行、跃迁、贸易和重进全流程,也未安装替换游戏插件;这项历史状态不代表后续版本的实机验收结果。离线结果不能替代对应功能的实际客户端验收。