上一 篇 我们把 SDK 和环境 都 准备 好了这篇 直接 进入 正题新建一个 能被 X-Plane 加载 的 插件。很多人 卡在 这 一步 不是 代码 写 不出来 而是 不知道 一个 插件 项目 到底 该怎么 建、 该 配 哪些 参数、 编译 出来 的 文件 怎么 放。 这 篇 我 用 Windows Visual Studio 2022 从 零 走 一遍 最终 得到 一个 会 在 日志 里 留 下 痕迹 的 win.xpl 文件。 不管 你 之前 是 玩 过 IDEA 插件、 Qt 插件 还是 前端 工具 扩展 只要 明白 “宿主 提供 API 插件 实现 入口 宿主 在 特定 时机 调用” 这套 模型 学 X-Plane 插件 会 非常 顺畅。 教程 默认 你 有 一 点 C/C 基础 至少 知道 函数、 指针、 编译 链接 零 基础 也 可以 先 照 着 敲 跑 通 之后 再 回头 补 细节。1. 动手之前先搞懂X-Plane插件到底是个啥1.1 从“飞机里的一个小程序”讲起X-Plane 插件 本质 上 就是 一个 动态 链接 库。 Windows 上 是 DLL Mac 上 是 dylib Linux 上 是 so。 它 没有 独立 的 main 函数 也 不会 自己 启动 而是 由 X-Plane 主 程序 在 启动 或 运行 中 动态 加载 按照 约定 调用 里面 几个 固定 名字 的 导出 函数。 你 可以 把 X-Plane 想象 成 一架 飞机 插件 是 你 塞 进 飞机 里 的 一台 小 设备 设备 本身 不 会 飞 是 飞机 给 它 供电、 提供 数据 它 才能 工作。 SDK 就是 设备 和 飞机 之间 的 接口 规范。“加载 进 进程” 这 件 事 很 重要。 插件 运行 在 X-Plane 的 进程 空间 里 内存 和 崩溃 范围 都 和 主 程序 一致。 所以 插件 里 如果 写 了 一个 野 指针 越 界 访问 崩 的 不是 插件 自己 而是 整个 X-Plane。 这 和 写 独立 的 控制台 程序 完全不同 和 写 浏览器 扩展、 IDE 插件 的 风险 模型 倒 是 很 像。1.2 SDK 里有什么下载 解压 之后 SDK 目录 下 有 几个 核心 部分 Include 目录 是 全部 头文件 Libraries 目录 是 各 平台 预编译 好 的 静态 导入 库 Examples 目录 有 官方 示例 代码。 头文件 里 最 常用 的 包括 XPLMPlugin.h、 XPLMUtilities.h、 XPLMDataAccess.h、 XPLMMenus.h。 文件 名 中 的 PLM 全称 Plugin Manager 后来 SDK 沿用 了 这个 缩写。 你 可能 在 文档 里 看到 XPLM300 这种 版本 号 它 表示 插件 API 版本 300 对应 X-Plane 11/12。 我们 不 用 死记 但 要 知道 宿主 和 SDK 版本 需要 兼容。Libraries 目录 下 的 .lib 文件 是 导入 库 里面 记录 了 X-Plane 主 程序 导出 的 API 符号。 写 代码 时 include 头文件 链接 时 把 对应 的 .lib 告诉 链接 器 生成 的 插件 体积 可以 很 小 因为 真 正 的 逻辑 实现 都 在 X-Plane 主 程序 里。 这 也就是说 插件 的 编译 流程 和 普通 DLL 基本 一样 只是 需要 额外 导 出 几个 特定 函数。1.3 五个必须导出的回调函数无论 插件 功能 多 复杂 都 必须 实现 5 个 回调 函数。 XPLMPlugin.h 里 有 明确 注释 我 整理 成 表 方便 看函数调用时机必须 返回主要 用途XPluginStart插件 被 加载 时int 非 0 表示 初始化 成功填写 插件 名称、 签名、 描述 做 基础 初始化XPluginStop插件 被 卸载 或 X-Plane 退出void释放 资源 清理 菜单、 注册 等XPluginEnable插件 被 启用 时int 非 0 表示 启用 成功可 以 开始 使用 功能 比如 开启 计时器XPluginDisable插件 被 禁用 时void停止 功能 但 不要 释放 全局 资源XPluginReceiveMessage收到 消息 时void处理 其他 插件 或 X-Plane 发来 的 消息有 人 会 疑惑 有 了 Start/Stop 为什么 还要 Enable/Disable 因为 X-Plane 允许 用户 在 运行 时 通过 “插件 管理器” 禁用 某个 插件。 禁用 时 XPluginDisable 被 调用 插件 要 停下 所有 正在 干活 的 部分 但 不能 把 内部 数据 结构 销毁 掉 这样 再次 启用 时 XPluginEnable 被 调用 能 快速 恢复。 这 种 设计 在 IDE 插件 的 activate/deactivate 概念 里 也 能 看到。 如果 你 只 写 了 Start 和 Stop 没有 考虑 禁用 场景 那么 用户 在 运行 中 禁用 再 启用 你 的 插件 很可能 出现 状态 丢失 甚至 崩溃。2. 新建项目从零到能编译出win.xpl2.1 环境说明与配置清单我 的 环境 是 Windows 11 Visual Studio 2022 Community X-Plane 12 正式 版 SDK 从 developer.x-plane.com 下载 的 最新 稳定 版。 用 Xcode 或 Linux 工具 链 的 话 思路 一模一样 只是 .lib/.xpl 文件 名 和 导出 方式 略 有 不同。 我 建议 新 入 坑 的 朋友 先 在 Windows VS 上 跑 通 因为 社区 里 大 部分 踩坑 案例 都 是 Windows 的 遇到 问题 容易 搜 到。项目 目录 我 放在 D:\dev\xplane\MyFirstPlugin SDK 解压 到 D:\dev\xplane\SDK。 这样 多个 插件 项目 可以 共用 一份 SDK 不用 每个 项目 都 拷贝 一份 头文件 和 库。 如果 你 的 X-Plane 安装 在 C 盘 系统 目录 建议 把 开发 目录 放 到 别 的 盘 避免 权限 问题 影响 编译 和 文件 拷贝。2.2 Visual Studio 空项目配置步骤打开 VS2022 创建 新项目 选 “空项目” 语言 选 C 项目 名 MyFirstPlugin。 创建 完 之后 项目 里 什么 都 没有 需要 手工 加 文件、 改 属性。第一 添加 源码 文件。 项目 名 右键 - 添加 - 新建项 - C 文件 命名 main.cpp。 虽 然 我们 写 的 是 C 风格 代码 但 用 .cpp 后缀 没 任何 问题 XPLM 头文件 有 extern “C” 保护。第二 配置 include 目录。 项目 属性 - 配置属性 - C/C - 常规 - 附加包含目录 添加 D:\dev\xplane\SDK\Include。 注意 是 顶层 Include 目录 里面 所有 XPLM*.h 都 在 那里。第三 配置 平台。 在 工具栏 上 把 解决方案 平台 从 Win32 切到 x64 配置 选 Release。 Debug 模式 不是 完全 不行 但 会有 额外 的 运行时 依赖 之后 专门 讲。 新手 阶段 用 Release 最 稳。第四 配置 链接 库。 链接 器 - 常规 - 附加库目录 添加 SDK 里 Libraries/Win/ 下 对应 编译器 版本 的 目录。 然后 链接 器 - 输入 - 附加依赖项 添加 XPLM_64.lib。 具体 文件名 以 你 下载 的 SDK 为 准 有的 版本 是 XPLM.lib 和 XPLM_64.lib 同时 存在 选 带 _64 的 那个 就是 64 位 导入 库。 如果 之后 用到 控件 系统 再 补 上 XPWidgets_64.lib。2.3 最小插件的源码新建 main.cpp 输入 下面 代码。 这是 一 个 最小 可 运行 的 插件 唯一 作用 就是 让 X-Plane 加载 它 并且 在 日志 里 打印 几 行 字。#include string.h #include XPLMPlugin.h #include XPLMUtilities.h PLUGIN_API int XPluginStart(char *outName, char *outSig, char *outDesc) { strcpy(outName, MyFirstPlugin); strcpy(outSig, com.example.myfirstplugin); strcpy(outDesc, A minimal X-Plane plugin); XPLMDebugString(MyFirstPlugin: XPluginStart called\n); return 1; } PLUGIN_API void XPluginStop(void) { XPLMDebugString(MyFirstPlugin: XPluginStop called\n); } PLUGIN_API int XPluginEnable(void) { XPLMDebugString(MyFirstPlugin: XPluginEnable called\n); return 1; } PLUGIN_API void XPluginDisable(void) { XPLMDebugString(MyFirstPlugin: XPluginDisable called\n); } PLUGIN_API void XPluginReceiveMessage(XPLMPluginID inFrom, int inMsg, void *inParam) { (void)inFrom; (void)inMsg; (void)inParam; }PLUGIN_API 是 XPLM 头文件 里 定义 的 宏。 Windows 上 它 会 展开 成 __declspec(dllexport) 保证 这 5 个 函数 出现在 DLL 的 导出 表 里。 Mac/Linux 上 它 会 对应 相应 的 可见性 修饰。 所以 跨 平台 代码 里 使用 这个 宏 就 够 了 不用 自己 判断 平台。XPluginStart 的 三个 参数 是 输出 缓冲区 宿主 已经 分配 好 内存 你 必须 用 strcpy 把 内容 拷 进去 而 不是 直接 把 outName 指向 一个 局部 字符串。 如果 乱 指 指针 宿主 拿 到 的 就是 栈 上 的 垃圾 数据 插件 管理器 里 可能 显示 乱码 甚至 直接 加载 失败。2.4 编译并检查输出直接 点 生成 解决 方案。 如果 没有 报错 在 项目 目录 的 Release/x64 下 会 出现 MyFirstPlugin.dll。 这 个 文件 要 改名 成 win.xpl 才 能 被 X-Plane 认识。 手动 复制 每次 都 容易 忘 我 习惯 在 项目 属性 - 生成事件 - 后期生成事件 里 加 一条 命令xcopy /Y $(OutDir)MyFirstPlugin.dll G:\X-Plane12\Resources\plugins\MyFirstPlugin\64\win.xpl把 路径 换成 你 自己 的 X-Plane 安装 目录。 这样 每次 编译 完成 自动 拷贝 省 掉 来回 拖 文件 的 时间。 注意 这个 命令 里 的 64 子目录 必须 存在 可以 在 命令 里 先 mkdir 或者 提前 建 好。3. 配置过程里的关键细节与踩坑记录3.1 平台位数32还是64为什么必须对齐这 个 问题 我 觉得 值得 单独 说 因为 踩 过 的 人 太多。 X-Plane 11 和 12 都 是 64 位 应用 所以 插件 必须 是 64 位 DLL。 但 网上 很 多 老 教程 还 在 用 32 位 配置 因为 X-Plane 10 时代 有 32 位 客户端。 如果 你 编译 出 32 位 win.xpl 放 到 64 位 X-Plane 里 日志 里 会 出现 类似 “Skipping plugin ... invalid architecture” 的 提示 插件 根本 不会 加载。VS 默认 的 解决方案 平台 可能 是 Win32 必须 手动 切 到 x64。 否则 即便 你 代码 没 问题 链接 器 拿 到 的 也 是 32 位 的 运行 库 和 导入 库。 想 确认 生成 的 DLL 是否 是 64 位 可以 用 开发者 命令 提示 符 运行dumpbin /headers MyFirstPlugin.dll | findstr machine看到 x64 就是 对 的 看到 x86 就要 重新 编译。 这 个 检查 在 排查 加载 问题 时 非常 有 用。3.2 字符集与C运行时两个容易翻车的坑Visual Studio 新 项目 默认 使用 Unicode 字符 集。 但 X-Plane SDK 的 所有 接口 都 是 char* 单 字节 版本 没有 宽 字符 重载。 把 项目 属性 - 常规 - 字符集 改 成 “使用 多字节 字符 集” 能 避免 很多 Windows API 泛型 别名 带来 的 编译 问题。 虽然 你 写 C 代码 可能 不用 直接 调用 Windows API 但 插件 后期 通常 要 操作 文件、 注册 表、 消息 框 提前 改 好 省 得 之后 突然 编译 报错。另一个 更 隐蔽 的 坑 是 C 运行时 库 选择。 Release 配置 下 默认 是 “多线程 DLL (/MD)” 这 个 一定 不要 改 成 “多线程 (/MT)”。 原因 很 简单 插件 是 被 X-Plane 进程 加载 的 X-Plane 自己 用 的 是 动态 CRT。 如果 插件 静态 链 入 CRT 那 插件 和 主 程序 各 有 一套 堆 管理, 插件 里 malloc 出来 的 内存 指针 要是 传 给 X-Plane 或 者 反向 传递 就 可能 因为 堆 不 一致 而 崩溃。 这种 崩溃 特别 难 查 因为 代码 看 起来 完全 正常 但 偶尔 崩 一次。 所以 从 一 开始 就 锁 死 /MD。3.3 导出符号.def文件怎么配有人 不 喜欢 依赖 PLUGIN_API 宏 那 也 可以 用 模块 定义 文件 显式 导出。 在 项目 里 新建 一个 myplugin.def 内容EXPORTS XPluginStart XPluginStop XPluginEnable XPluginDisable XPluginReceiveMessage然后 在 项目 属性 - 链接器 - 输入 - 模块定义文件 里 指定 这 个 def。 这样 生成的 DLL 导出 表 就 只有 这 5 个 函数 干净 且 可控。 但 我 个人 还是 推荐 用 PLUGIN_API 宏 因为 代码 跨 平台 编译 时 不用 为 每 个 平台 维护 def。 不管 用 哪种 方式 导出 函数 的 名称 一定 要 和 XPLM 文档 里 完全 一致 大小 写 也不行。 X-Plane 加载 时 通过 GetProcAddress 找 这些 符号 少 一个 字母 就 会 直接 说 “Unable to load”。3.4 把插件装进X-Plane目录命名有讲究X-Plane 扫描 的 根目录 是 Resources/plugins。 每 个 插件 通常 是 一 个 子目录 里面 按 平台 再 分 一层。 比如 我 的 目标 路径 是G:\X-Plane12\Resources\plugins\MyFirstPlugin\64\win.xpl其中 64 表示 64 位 架构 win.xpl 是 Windows 平台 的 文件 名。 如果 你 还 想 支持 Linux 再 加 一个 64/lin.xpl Mac 是 64/mac.xpl。 这 是 X-Plane 的 硬性 规定 不 能 改。 有 时候 看到 别人 的 插件 目录 里 是 32/win.xpl 那 是 为了 兼容 旧版 32 位 客户端 对 现在 的 X-Plane 12 没 意义。需要 注意 Resources/plugins 下 的 子目录 才是 插件 直接 把 win.xpl 扔 到 plugins 根目录 通常 不会 被 加载。 子目录 名 可以 任意 但 建议 用 插件 名 方便 识别。 另外 如果 你 的 插件 文件 名 不是 win.xpl 而是 MyFirstPlugin.xpl X-Plane 也 不会 认。 每次 拷贝 完 之后 检查 一下 文件 名 和 路径 这种 低级 错误 真 的 会 浪费 半 小时。4. 在X-Plane里跑起来加载验证与调试技巧4.1 启动X-Plane看Log.txt安装 好 之后 启动 X-Plane 然后 打开 X-Plane 根目录 下 的 Log.txt。 这 个 文件 每次 启动 都 会 覆盖 是 排 查 插件 问题 的 第一 入口。 搜索 你 的 插件 签名 com.example.myfirstplugin 如果 看到Loaded: Resources/plugins/MyFirstPlugin/64/win.xpl (com.example.myfirstplugin).说明 加载 成功。 再 往 下 翻 应该 能 找到 我们 用 XPLMDebugString 输出 的 “MyFirstPlugin: XPluginStart called”。 如果 没有 这 行 说明 XPluginStart 没有 被 调用 或 者 调用 时 崩溃 了。 注意 Log.txt 日志 会 有 延迟 写入 的 情况 吗 X-Plane 通常 是 边 写 边 刷 新 但 如果 崩溃 在 XPluginStart 内部 日志 可能 停 在 加载 那一 行。 这时 就 要 用 下 面 的 调试 方法。我 建议 开发 期间 把 Log.txt 固定 在 一个 编辑 器 标签 页 每次 运行 前 清空 或 者 记住 当前 末尾 位置 这样 插件 输出 能 第一时间 捕捉 到。4.2 菜单项让用户能点到你的插件只 写 日志 的 插件 无法 交互 我们 给 它 加 一个 菜单 项。 这 一步 会 让 你 看到 插件 完整 的 “加载 - 用户 触发 - 输出” 流程。 先 include XPLMMenus.h 然后 在 XPluginStart 里 创建 菜单。#include XPLMMenus.h static XPLMMenuID gMenuID; static int gMenuItem; void MyMenuCallback(void *inRefcon) { XPLMDebugString(MyFirstPlugin: menu clicked\n); } // 在 XPluginStart 中 原有 strcpy 之后加 XPLMMenuID pluginsMenu XPLMFindPluginsMenu(); gMenuID XPLMCreateMenu(My First Plugin, pluginsMenu, -1, NULL, NULL); gMenuItem XPLMAppendMenuItem(gMenuID, Click Me, (void *)1, MyMenuCallback);这 段 代码 的 含义 找到 系统 的 Plugins 菜单 在 里面 创建 一个 名为 “My First Plugin” 的 子菜单 然后 在 这个 子菜单 里 加 一个 “Click Me” 条目。 当 用户 点击 这个 条目 时 MyMenuCallback 被 调用。 要 注意 的 是 XPLMCreateMenu 的 第 三 个 参数 传 -1 表示 直接 作为 Plugins 菜单 的 子 菜单 挂载 如果 传 其他 值 含义 是 父 菜单 中 某个 条目 的 索引。 新手 容易 把 这个 参数 搞 混。在 XPluginStop 里 最好 销毁 菜单if (gMenuID) XPLMDestroyMenu(gMenuID);不 销毁 的 话 插件 卸载 再 加载 时 可能 会 创建 出 重复 的 菜单 项。4.3 读取飞机位置和飞行模拟器对话菜单 只是 入口 插件 真正 的 价值 在 于 读写 X-Plane 的 数据。 这 一步 我们 让 插件 读取 当前 飞机 的 纬度 和 经度。 X-Plane 的 数据 访问 接口 是 XPLMDataAccess.h 所有 数据 都 通过 字符串 路径 标识 比如 sim/flightmodel/position/latitude。在 XPluginStart 里 获取 DataRef 句柄#include XPLMDataAccess.h static XPLMDataRef latRef; static XPLMDataRef lonRef; // 在 XPluginStart 中 latRef XPLMFindDataRef(sim/flightmodel/position/latitude); lonRef XPLMFindDataRef(sim/flightmodel/position/longitude);然后 改 菜单 回调void MyMenuCallback(void *inRefcon) { float lat XPLMGetDataf(latRef); float lon XPLMGetDataf(lonRef); char buf[256]; snprintf(buf, sizeof(buf), MyFirstPlugin: lat%.6f lon%.6f\n, lat, lon); XPLMDebugString(buf); }这样 每次 点 菜单 项 日志 里 就 会 出现 当前 飞机 位置。 XPLMFindDataRef 返回 的 句柄 在 插件 生命周期 内 一直 有效 不用 每次 读取 都 重新 查 字符串。 这 是 一 个 很 重要 的 性能 习惯。 写 入 数据 也 是 类似 用 XPLMSetDataf、 XPLMSetDatai 等 后面 做 自动驾驶 辅助 时 会 用 到。4.4 写日志和调试别再弹MessageBox新手 调试 插件 时 特别 喜欢 用 MessageBox 弹 窗。 在 普通 程序 里 没 什么 但 插件 运行 在 X-Plane 进程 内 弹 窗 会 阻塞 整个 模拟 器 的 渲染 循环 全屏 模式 下 窗口 还 可能 在 后台 导致 模拟 器 “假死”。 正确 的 做法 是 用 XPLMDebugString 输出 到 Log.txt 或 者 自己 写 一个 简单 的 日志 文件 函数。 如果 你 实在 想 在 调试 器 里 看 输出 可以 用 OutputDebugStringA 在 VS 里 附加 到 X-Plane 进程 后 能 在 输出 窗口 看到 但 这个 操作 对 新手 来说 反而 增加 复杂 度。另外 一个 建议 在 插件 里 预埋 几 个 调试 菜单 项 比如 “输出 状态”、“重置 数据”。 这样 每次 改 完 代码 后 不用 重 启 X-Plane如果 用 了 重载 插件 功能 也 能 快速 验证 功能 是否 正常。5. 常见问题加载失败与异常行为速查表5.1 插件不加载Log里没有任何行如果 Log.txt 里 完全 找 不到 你 的 插件 名 先 按 下面 顺序 查检查项正确 值错误 示例路径Resources/plugins/MyFirstPlugin/64/win.xpl直接 放 plugins 根目录文件 名win.xplMyFirstPlugin.xpl架构x64x86导入 库XPLM_64.libXPLM.lib32 位导出 函数5 个 全部 存在漏 了 一个最 烦 人 的 是 路径 完全 正确 但 还 是 没 加载。 这时候 用 Dependency Walker 或者 Dependencies 工具 打开 win.xpl 看 导入 表 里 是 否 有 不 存在 的 系统 DLL 特别 是 VCRUNTIME140.dll。 如果 你 用 静态 CRT 编 译 导入 表 里 可能 没有 这 个 dll 但 也 可能 因此 加载 失败。 最 稳 妥 的 方案 就是 回到 /MD。5.2 加载后崩溃或与其他插件冲突插件 加载 时 崩溃 大部分 是 在 XPluginStart 里 做了 不该 做 的 事。 比如 尝试 创建 窗口、 访问 某些 飞行 模型 数据。 记住 XPluginStart 调用 时 X-Plane 的 插件 系统 才 刚刚 初始化 一部分 不是 所有 功能 都 可用。 这 时候 只 做 变量 初始化和 资源 申请 真 正 的 逻辑 放到 XPluginEnable 或 菜单 回调 里。另外 插件 之间 可能 会 有 冲突。 比如 两个 插件 都 往 同一个 菜单 项 位置 插入 或者 都 监听 某 全局 消息 并对 数据 做 修改。 排查 时 把 Resources/plugins 下 其他 插件 临时 移走 只 留 你 的 插件 复现 问题。 如果 这样 就 不 崩了 那 就是 和 某个 插件 的 兼容 性 问题。 这种 冲突 很 难 从 代码 层面 完全 避免 只能 在 设计 时 尽量 少 用 全局 状态 利用 签名 机制 区分 插件。5.3 函数没反应生命周期理解偏差常见 情况 是 菜单 创建 成功 但 点击 没 反应。 原因 通常 是 回调 函数 没 注册 对。 如果 你 用 XPLMCreateMenu 时 传 了 NULL handler 而 XPLMAppendMenuItem 时 又 没 传 handler 那 这 个 菜单 项 就 没有 任何 处理器 自然 没 反应。 我 当时 就 犯 过 这 个 错 以为 XPLMCreateMenu 的 handler 会 自动 作用 于 所有 子 项 结果 只是 默认 处理器 子 项 可以 单独 覆盖。还有 一种 情况 插件 加载 时 显示 在 插件 管理 器 里 是 “禁用” 状态 XPluginEnable 没 被 调用。 此时 插件 的 某些 交互 可能 不 生效。 检查 Log 里 是否 有 XPluginEnable called 这 一行 没有 的话 看 一下 是不是 XPluginStart 返回 了 0。 返回 0 表示 初始化 失败 插件 会 被 直接 卸载 所有 后续 回调 都 不会 发生。5.4 插件无法卸载或重复加载开发 时 最 频繁 的 操作 是 替换 win.xpl 然后 重 启 X-Plane。 但 Windows 下 DLL 被 进程 加载 后 会 锁住 文件 如果 不 退出 X-Plane 就 覆盖 win.xpl 系统 会 提示 文件 被 占用。 这 时候 要么 关 掉 X-Plane 要么 用 X-Plane 自带 的 “开发者 菜单 - Reload Plugins” 功能。 Reload Plugins 会 先 卸载 所有 插件 再 重新 加载。 如果 你 的 插件 没有 在 XPluginStop 里 释放 全部 资源 重 载 后 可能 出现 双 重 初始化 导致 的 状态 混乱。 所以 开发 插件 时 要 保证 Start 和 Stop 是 配对 的 Start 里 创建 的 东西 Stop 里 一定 要 释放。 我 的 习惯 是 快 速 迭代 时 用 Reload Plugins 遇到 诡异 问题 就 老老实实 重启 X-Plane。最后 再 分享 一个 小 技巧 写 XPluginStart 时 把 插件 签名 起 得 唯 一 一点 不要 用 什么 “hello123” 这种 推荐 逆 域名 风格 比如 com.yourname.pluginname。 这 不仅 是 为了 规范 更 是 为了 在 Log 里 好 搜索 也 减少 和 别人 插件 冲突 的 概率。 踩 过 几 次 坑 之后 你 会 发现 新建 X-Plane 插件 本身 真 的 不 复杂 复杂 的 是 那些 看 不见 的 配置 细节。 把 这 篇 的 环境 配置 和 生命周期 吃 透 后面 再 做 仪表、 工具、 自动化 飞行 辅助 都 是 在 这 个 架子 上 加 肉 的 事。
阅读完成 · 觉得有帮助?