SOUI5 —— 一套 C++ 代码覆盖六端的国产原生 GUI 框架
SOUI5 —— 一套 C++ 代码覆盖六端的国产原生 GUI 框架
获取代码: git clone https://gitee.com/setoutsoft/soui4 soui4 –recursive
安装依赖包: ubuntu: sudo apt-get update && sudo apt install -y cmake build-essential xvfb libxcb1-dev libxcb-render0-dev uuid-dev libasound2-dev libgl1-mesa-dev freeglut3-dev pkg-config mingw-w64 –fix-missing macos: brew install ninja pkgconf glfw glew mingw-w64
代码编译: 项目使用cmake管理编译配置,进入工程目录(如cd soui4) mddir build cd build cmake .. make -j4
0. 方案速览(一页读懂)
| 维度 | 内容 |
|---|---|
| 一句话定位 | 以 Win32 API 语义为统一编程面的 C++ DirectUI 框架,让同一套 C++ UI 与业务代码在 Windows / Linux / macOS / iOS / Android / OpenHarmony 六端原生运行 |
| 选型定位 | 不是”Qt / Flutter 的通用替代品”,而是”存量 Win32 资产信创迁移”场景下的必要选项——在”框架生态成熟度 / 用户数量 / 大厂支撑”上确实弱于 Qt、Flutter;但在”让既有 Windows 程序低成本跨平台“这一能力上,目前只有 SOUI5 这条路线保留(Wine 属运行时兼容、目标不同,Qt / Flutter 不提供该能力)——详见 §1.6 |
| 解决的核心问题 | 信创环境下,海量 Windows C++ 客户端资产无法在国产 Linux / 鸿蒙上复用,必须迁移;而现有的”Qt 重写”与”Wine 兼容”两条路代价高、可行性差,移动端尤其缺位 |
| 最硬的技术证据 | 跨平台样板 games/cnchess 的核心绘制与业务源码中 __ANDROID__ / __OHOS__ 出现次数均为 0,”一次编写、六端运行”是工程现实而非口号 |
| 核心技术资产 | 自研跨平台兼容层 swinx(225 个文件 / 168,472 行,45 个头文件中 30 个与 Windows SDK 同名同结构、gdi.h 对应 SDK wingdi.h) |
| 自有框架源码 | 框架主体 868 个文件 / 323,425 行(内核 SOUI/ 149,310 + utilities/ 35,351 + 16 个组件 components/ 86,094 + 扩展控件 controls.extend/ 52,670,均排除 vendor/third-part);连同 swinx 168,472 行 |
| 兼容层完成度(硬数据) | api_scan 实测:swinx 声明 Win32 API 1,066 个,其中有定义 937 个;按实现分类 真实实现 894 / 桩 37 / 部分实现 6——是”重演”而非”补头文件的空桩”;且由 swinx-api-gate.yml 门禁保证 API 面只增不减 |
| 体积(发行实测) | 内核 soui4.dll(VS2008 x86、/MT 静态 CRT、含全部核心控件)2,426,880 B(2.31 MiB)——这就是正常发行场景;组件按需装载、选型直接影响体积——render-gdi.dll 147,968 B(0.14 MiB) ↔ render-skia.dll 1,652,736 B(1.58 MiB)(约 11 倍)(数据与口径见 §3.2、§5.1) |
| 可组合性 | 能力按场景选、界面按需长:16 个组件像积木一样挑选替换(选型决定体积与功能),皮肤 / 布局 / 窗口三维可无限扩展,XML 布局达成 UI 与逻辑分离 |
| 质量保障 | 427 条无头自动化用例(其中门禁标签 soui-headless 约 422 条),4 个 GitHub Actions 工作流,含 swinx API 面回退门禁 |
| 存量背书 | 项目方自述持续开发 15 年(自 2011 年开源起算;本仓库 git 历史始于 2018-06,见 §7);已落地迅游、恒星播放器、航信全票通、月轮加速器、熊猫加速器、老版本百度网盘,启程输入法 等数十款商业产品 |
| 开源社区 | 47 位贡献者、2,909 次提交、24 个发布 tag(最新 5.3.2.1);SOUI 3+ 授权(个人免费 / 公司收费,贡献者终身免费);第三方与派生代码在 license_CN.txt / license_EN.txt 逐项披露 |
| 国产化落点 | 已适配 OpenKylin / UOS / deepin 等国产 Linux 发行版,并以 OpenKylin 社区上游仓库形态在信创体系内分发 |
| 成长方向 | 已具备”让既有 Win32 程序低成本跨端”的框架能力本身(兼容层重演 Win32 语义);该能力正沿”补齐迁移面”方向收敛为开箱即用 |
核心创新骨架(详见 §四):本方案的技术创新凝练为四条核心,分别对应路线、工程方法学、架构、资源与分发——① 以”重演 Win32”替代”抽象 Win32”的跨平台路线;② “声明式重述 UI + 原样保留 Win32 逻辑”的迁移方法学;③ 平台 × 渲染二维正交 + 版本化 PlatformAPI 契约的可扩展架构;④ 全桌面平台 .rc 跨平台编译 + 运行时资源解析 + 单文件分发。四者互为支撑,共同构成本方案的技术辨识度。在此之上,时间轴动画引擎、SVG 低成本 HiDPI、16 组件积木式选型、Lua 脚本层等工程能力进一步补强框架的可用性与发行弹性(见 §4.5、§五)。
一、项目背景
1.1 行业痛点一:Windows 客户端资产的”信创断点”
在国家推动信息技术应用创新(信创)的背景下,政企、金融、工业、能源等行业的客户端软件面临一个共同的现实:存量资产几乎全部是 Windows C++ 程序。
这些程序的资产结构有三个特征:
- 业务逻辑与 UI 高度耦合:界面代码、交互逻辑、业务规则混在几十万行 C++ 里;
- 深度依赖 Win32:窗口消息、GDI 绘制、COM 组件、内核对象、公共控件贯穿全局;
- 迁移预算有限:不可能为一个已有产品重新招团队、换语言、从头写一遍。
把这些资产迁到国产 Linux,现实中的两条主流路径各有硬伤:
路径一:用跨平台框架重写(以 Qt 为代表)。 代价有三重:
- 工作量巨大:几十万行 C++ 业务要面向框架自有 API(
QWidget体系、信号槽、QObject内存模型)重写,界面层几乎全部推翻; - 授权成本:LGPL 对闭源商业产品构成合规负担,商业授权费用昂贵;
- 移动端支持不友好:Qt 在移动端要求 UI 必须跑在独立于系统主线程的专用 UI 线程上,于是不仅”业务线程 ↔ UI 线程”的交互要额外加锁/排队,与系统自身的交互也变得别扭(如系统 UI 的切入切出、系统级生命周期事件)。项目方观察,这也是 Qt 在移动端的社区规模与生产案例显著小于桌面端的重要原因之一(定性观察,非统计结论)。
路径二:靠 Wine 做二进制兼容。 据公开信息,OpenKylin、deepin 等国产发行版都在持续完善 Wine 以直接运行 Windows 软件,但实际效果并不理想:对简单的小程序或许可行,然而大型复杂项目依赖的 Win32 API 面极宽、且对特定版本行为有隐式假设,二进制兼容无法穷尽这些不可控因素——这条路对大中型项目的现实可行性很低。
SOUI5 提供的是第三条路:用 SOUI5 把现有 Windows 程序重写迁移,但不是”从零重写”。
| 迁移路径 | 工作量 | 授权成本 | 移动端 | 可行性 |
|---|---|---|---|---|
| Qt 重写 | 高(业务面向新 API 重写) | 高(LGPL 合规 / 商业授权) | 差(双 UI 线程,跨线程协调别扭) | 桌面可行;移动端社区与案例显著更小(项目方观察) |
| Wine 二进制兼容 | 低(不改代码) | — | 无(仅桌面) | 小程序可行,大型复杂项目不可控 |
| SOUI5 重写迁移 | 中低(UI 用声明式 XML 重描述,逻辑可大量保留) | 无(自有授权,个人免费 / 商用收费) | 原生六端 | 大中小项目均可落地 |
须区分”成本高低”与”目标不同”:上表前三列比较的是”迁移成本”,但 Wine 与另两条路并不在同一目标上——Qt 重写与 SOUI5 迁移产出的是目标平台的原生构建(程序被真正移植),而 Wine 是运行时二进制兼容:不改代码让旧程序跑起来,但程序并未被移植。这一区别是 §1.6 论证的核心,详见该节。
之所以能做到”中低工作量”,是因为 SOUI5 的两项框架能力正好命中重写迁移的两个主要成本项:
- 声明式 UI(XML):界面用 XML 描述(控件树、属性、皮肤、布局),UI 与逻辑分离——界面层可以快速重描述,而不是把几十万行里的绘图代码逐行改写成新框架的 API 调用;
- 原生 Win32 API 兼容:
swinx提供了完整的 Windows 内核对象支持(事件 / 互斥体 / 信号量 / 可等待定时器 / 定时器队列 / 文件映射、WaitForSingleObject/WaitForMultipleObjects等),原有业务逻辑中基于 Win32 内核对象的同步、等待、线程协作代码可以 0 成本迁移,无需改写成另一套线程/同步模型。
该能力已由源码核实:swinx/src/sysobjs.cpp(2,381 行)实现了CreateEvent/CreateMutex/CreateSemaphore/CreateWaitableTimer/CreateTimerQueue*/CreateFileMapping+MapViewOfFile/WaitForSingleObject/WaitForMultipleObjects等完整内核对象面(swinx/include/sysapi.h声明,sysobjs.cpp实现),无名对象底层以管道 fd +select()承载等待语义(sysobjs.cpp:1935/1941,助手selectfds:1900-1971),文件映射以shm_open+mmap MAP_SHARED(:2306,Android 走ASharedMemory_create)——是真实实现,而非仅补头文件的空桩。
需要客观说明的是”0 成本”的适用范围:上述内核对象是进程内使用的成熟实现;跨进程按名字共享的内核对象(命名对象)在非 Windows 平台受限于各自的跨进程机制,迁移时可能需要评估。这些不影响”业务逻辑层面的同步代码可整体保留“这一主线结论。
换句话说:SOUI5 迁移的是”UI 层用声明式方式重描述 + 业务层几乎原样保留“,而不是 Qt 那种”业务层也要面向新 API 重写”。
并且,SOUI5 已具备支撑”直接迁移既有 Win32 程序”的底层能力。 当前的迁移方式是”用 SOUI5 重写迁移”,但支撑”直接迁移既有 Win32 程序”所需的底层能力——以兼容层重演 Win32 语义——已经是这套框架的既定路线与既有资产;需要时,完全可以在现有框架基础上把这一需求变为现实(详见 §5.6 边界说明与 §1.6)。
1.2 行业痛点二:一个产品、每个平台一份代码
第二个痛点来自另一个方向:当 Qt 这类框架对移动端支持有限时,很多项目被迫”一个产品每个平台各写一份代码”——Windows 一份、Linux 一份、Android 一份、iOS 一份、鸿蒙一份。多端各自维护,人力翻倍、版本漂移、缺陷要在多处重复修复。
近年来不少项目转向 Flutter 来解决跨平台问题:Flutter 对移动端的支持确实明显好于 Qt,但其代价是换语言(Dart)+ 背一套自带渲染引擎与 VM,既有 C++ 资产与 Win32 技能栈无法复用,且桌面端能力相对薄弱。SOUI5 的”六端统一”为这一类问题提供了另一种值得评估的解法:
| 方案 | 语言 | 资产复用 | 移动端 | 桌面端 |
|---|---|---|---|---|
| 每平台一份代码 | 各平台原生语言 | 无 | 各自原生 | 各自原生 |
| Qt | C++ | 需重写 | 差(双 UI 线程) | 好 |
| Flutter | Dart | 无法复用 C++ | 好 | 一般 |
| SOUI5 | C++(Win32 风格) | 既有 C++ / Win32 资产直接复用 | 原生六端 | 原生六端 |
SOUI5 的答案是:一份 C++ 代码 + 一份 XML 界面描述,同时覆盖桌面与移动共六端——既有资产不归零,多端维护收敛为一份(§4.2 给出”零平台宏”的硬证据)。
需要公允承认:Flutter 在移动端生态、第三方组件丰富度、UI 表现力与团队上手速度上具备明显优势,是全球范围内跨平台移动开发的主流选择之一;SOUI5 与之并非”替换关系”,而是面向”已有大量 C++ / Win32 资产、且需要覆盖桌面“这一特定场景的另一条技术选型。若项目是纯新建、以移动为主、团队无 C++ 包袱,Flutter 往往是更省力的起点。本方案的主张是”为存量 C++ 资产提供一个低迁移成本的六端方案”,而非”取代 Flutter”。
swinx 兼容层于 2024 年底启动(git 首个提交 2024-11-28),2026 年 10 月发布 1.6 与 1.7(当前 1.7),是这套方案最年轻也最关键的一块;其代码来源构成(自研为主 + 少量已披露的 Wine 派生)见 §2.2 末。
1.3 三条国产化路径的技术路线对比
跨平台 GUI 的技术路线,本质上是四种选择,SOUI5 走的是最难走、也最少人走的那一种:
| 路线 | 代表 | 跨平台怎么实现 | 团队要付的代价 |
|---|---|---|---|
| 换语言 | Flutter、Electron、React Native | 用另一门语言写 UI,各自渲染 | C++ 资产与技能栈归零,还背运行时 |
| 自建抽象 API | Qt、wxWidgets | 定义框架自己的 API,各平台分别实现 | 仍要 C++,但业务要面向新 API 重写 |
| 自绘引擎 | Flutter、Skia 系 | 自带渲染引擎直接画 | 换语言 + 背 VM |
| 重演平台本身 | SOUI5 | 让 Windows 的 API 面在别的平台上成立 | 需自研兼容层(swinx 168,472 行) |
SOUI5 选择的是第四条路:不去抽象或替换 Windows,而是让 Windows 的 API 面在别的平台上”重新成立”——写一个兼容层,把 Win32 语义在 Linux / macOS / iOS / Android / OHOS 上重演出来。代价是这层兼容层要自己写、自己维护;收益则最为直接:
已有的 Win32/WTL 编程知识、已有的 SOUI C++ 代码,在新平台上不是负债,而是可以继续增值的资产。
对”最难走”的自我审视:这条路的代价是真实的——兼容层的维护责任全部落在项目自己身上,Win32 API 面越铺越宽,长期维护成本高于”定义小 API 面”的抽象路线;且该路线的收益只在”已有 Win32 资产”的场景下才成立,对全新项目反而是负担。SOUI5 的选择是把这份成本集中在框架侧一次性投入,从而把收益让给所有复用 Win32 资产的项目。
1.4 信创与 Qt 国产替换的契合点
| 诉求 | SOUI5 的对应能力 |
|---|---|
| 国产 Linux 适配 | 已适配 OpenKylin / UOS / deepin;swinx 基于 XCB/X11 + Cairo 自建窗口系统,不依赖发行版 Qt 版本 |
| 鸿蒙原生支持 | OHOS 为正式支持平台而非社区补丁,经 PlatformAPI 桥 + soui-ohos-lib(HAR 包)接入 EntryAbility |
| 授权自主可控 | 自有商业授权条款(个人免费 / 商用收费),不受 LGPL 传染与商业授权约束;swinx 内含 Wine 派生代码已单列披露与合规说明 |
| 不绑发行版组件版本 | cairo / fontconfig / freetype / xkbcommon / dbus / skia 等全部源码 vendor 化,构建不依赖发行版提供什么版本 |
| 迁移成本可控 | 业务层零平台宏,平台差异被兼容层与薄入口吸收;UI 用声明式 XML 重描述,Win32 逻辑可直接保留 |
对 Qt 的差异化:Qt 以 QPA 平台抽象层实现跨平台,原生调用需切换/桥接线程,移动端还须维护独立 UI 线程;且 LGPL 授权对闭源商业产品构成合规负担。SOUI5 则以”重演 Win32”实现跨平台,原生能力经 JNI/NAPI 在同一线程同步调用,不需要双 UI 线程,授权条款明确。
公允起见:Qt 是经过大规模生产验证的成熟框架,其文档、工具链(Qt Creator / Designer)、第三方生态与社区规模都远非 SOUI5 可比;Qt 的 QPA 抽象也让它在”全新项目、不依赖 Win32 资产”时具备更好的可移植性与长期可预期性。SOUI5 的差异化只在“存量 Win32 资产迁移”与”授权自主”两个具体维度上成立,不宜泛化为”SOUI5 整体优于 Qt”。
1.5 在信创背景下,SOUI5 的必要性
SOUI5 在框架成熟度、用户数量、大厂支撑上确实落后于 Qt、Flutter,这一点无须回避。但参赛方案要说明的不是”SOUI5 比谁更好”,而是在信创迁移这一特定场景中,SOUI5 是否够用、是否补上了空白。答案取决于一个容易被忽略的区分:生态成熟度与”迁动存量 Windows 资产”的能力,是两个相互独立的维度——生态规模再大,也不能替客户把几十万行 Win32 C++ 迁到国产平台。
在这个”能力维度”上,各方案的定位如下:
| 方案 | 能否让存量 Win32 程序低成本跨端 | 原因 |
|---|---|---|
| Qt | 不能 | 跨平台靠自建 QPA 抽象层,既有 Win32 代码须面向 Qt API 重写 |
| Flutter | 不能 | 跨平台靠换语言 + 自带引擎,C++ / Win32 资产无法复用 |
| Wine | 非”跨端”,属运行时兼容 | 不改代码让旧程序在 Linux 上运行,但不产出目标平台原生构建、不接平台系统能力、移动端不通 |
| SOUI5 | 能(当前唯一路线) | 跨平台方式本身就是”在其它平台重演 Win32 语义”,资产复用是路线前提而非附带好处 |
Wine 与另三者不在同一目标上——它让旧程序”继续运行”,而 SOUI5 让资产”被迁成目标平台的原生应用”;二者不构成同一能力项的竞争。
与 winelib 的边界(同一路线思想下的覆盖面之差):Wine 的 winelib 模式允许把 Win32 源码链接到 Wine 的 Win32 实现上、在 Linux 上编译出原生 ELF——与”重演 Win32 + 产出原生构建”共享同一条路线思想。二者的差别在目标覆盖面:winelib 的场景是桌面 Linux 上的源码 / 二进制兼容,不覆盖 Android / iOS / OHOS 等移动与嵌入式平台,不提供 UI 框架层(DirectUI 控件、皮肤、XML 布局、动画、MVC 虚拟列表),也不处理国产 OS 发行版的集成与分发形态;SOUI5 提供的是”兼容层 + 完整 UI 框架 + 六端(含移动)+ 版本化 PlatformAPI 契约“的产品级方案。简言之:winelib 回答”怎么让桌面 Linux 跑起来”,SOUI5 回答”怎么迁成六端原生应用并长期维护下去”。
因此,SOUI5 的价值不在于”更优”,而在于补上了一个空白:
在”(1)有大量存量 Windows C++ 资产、(2)需迁移到国产平台(含移动端)、(3)不推倒重来”三者交集里,SOUI5 是目前少数满足全部条件的选项——它够用,且当前只有它走这条路。
必要的克制:”唯一”是基于 2026-10 公开技术路线的判断,不排除未来出现同类实现;SOUI5 的”0 成本跨平台”目前是”能力已具备、迁移面待补齐”,尚非开箱即用(见 §5.6);若项目没有存量 Win32 资产、或无需覆盖桌面,本节结论并不适用,应回归常规选型。
二、技术架构
2.1 三根支柱:为什么是”三根”,以及每一根回答什么问题
SOUI5 的架构可以概括为”一个内核 + 三根支柱 + 一个配套机制“。说清”为什么是支柱、为什么恰好是三根”,比罗列组件更重要——一根支柱之所以是支柱,是因为它回答了一个其它支柱无法替代的问题;抽掉它,整套方案的价值主张就会塌掉一块。
三根支柱分别回答三个彼此独立、且构成链条的问题:
| 支柱 | 回答的问题 | 抽掉它会怎样 |
|---|---|---|
| 支柱一 · swinx 兼容层 | 可移植性:同一份代码能不能在别处跑起来? | 必要条件,抽掉它一切免谈;但只有它,你得到的是”能编译”,不是”能好用” |
| 支柱二 · 平台 × 渲染二维正交 | 可扩展性:六端之后,再加一端、再加一个渲染后端,边际成本是加法还是乘法? | “六端”退化成一次性的英雄主义搬运,架构无法持续吸收新平台 |
| 支柱三 · SOUI 高性能 UI 框架 | 可开发性 / 可维护性:代码在六端都跑起来之后,界面能不能被高效搭出来、长期维护下去? | 迁过去的是”一份能跑但难以维护的旧界面代码”,信创客户拿到的是技术债平移,而非资产延续 |
一句话概括三根支柱的分工:支柱一让”平台”消失,支柱二让”扩展”变成加法,支柱三让”开发”回归日常。 它们对应”能不能跑 / 能不能一直跑到更多地方 / 跑起来之后好不好用”三把不同的尺子——这正是”三根支柱才具有稳定性”的原因:两根只能覆盖其中两问,必然在第三问上留下塌方。
graph TD
subgraph 支柱三["支柱三:SOUI 高性能 UI 框架(可开发性/可维护性)"]
B["内存模型 · 皮肤渲染抽象 · XML 布局语言 · 动画引擎 · 布局系统 · MVC 控件"]
end
subgraph 支柱一["支柱一:swinx 兼容层(可移植性)"]
C["Win32 API 面重演:user32/gdi/ole/sysobj/richedit/scintilla/oleacc"]
end
subgraph 支柱二["支柱二:平台 × 渲染二维正交(可扩展性)"]
D1["platform/ 平台适配(linux/cocoa/ios/mobile)"]
D2["gdi/ 渲染后端(gdi/cairo/apple)"]
end
A["应用层:业务 C++ + XML 布局 + Lua 脚本"] --> B
B --> C
C --> D1
C --> D2
D1 --> E["Windows / Linux / macOS / iOS / Android / OpenHarmony"]
D2 --> E
配套机制(§2.5):异步任务与线程协作。它不决定”能不能跨平台、能不能搭界面”,而决定”跨平台之后好不好用、好不好维护”——属于工程配套,不计入支柱。
下面三节逐一展开:每根支柱先重述它回答的问题,再给出”它凭什么能答上来”的硬证据,最后点明”抽掉它会失去什么”。
2.2 支柱一:以 Win32 为”世界语”(回答”可移植性”)
win32 是什么?它是 Windows 开发者三十年来积累的那一整套 API 母语——窗口、消息、GDI 绘制、内核对象、COM/OLE。swinx 是一层跨平台的 Win32 兼容桥接层:它在 Linux / macOS / iOS / Android / OpenHarmony 上把这套 API 面重新实现了一遍,让 SOUI5 内核(以及上层业务代码)继续用 Windows 开发者的母语来写,而无需为每端另写一套 UI 框架。
凭什么答”可移植性”——不是”补了同名头文件”,而是”真实重演了 API 面”。 判据是一个可机器复核的数字(swinx/doc/tools/api_scan.py --check,由 .github/workflows/swinx-api-gate.yml:28 在每次 PR 强制比对):
| api_scan 实测分类 | 数量 | 含义 |
|---|---|---|
| swinx 声明的 Win32 API | 1,066 | 覆盖宽度 |
| 其中有定义 | 937 | 非空声明 |
| 按实现性质分:真实实现 | 894 | 有可运行逻辑 |
| 按实现性质分:桩(stub) | 23 | 仅占位 |
| 按实现性质分:部分实现 | 6 | 局部实现 |
也就是说,已定义的 Win32 API 中九成以上(894/937)为真实实现,swinx/include/ 提供的 45 个头文件里有 30 个与 Windows SDK 同名同结构(windows.h/winuser.h/commctrl.h/oleacc.h/textserv.h…,另 gdi.h 对应 SDK wingdi.h),因此 SOUI5 内核直接 #include <windows.h>,业务层零平台 #ifdef。
真正的意义不在”同名同构”,而在”覆盖的宽度 + 行为的保真”。 不少跨平台方案只重演了窗口与绘图(UI 层 API);swinx 的价值在于它把 Windows 开发中日常依赖、却常被跨平台框架忽略的一整类 API 也一并真实重演了——
- UI 层 API(
user32/gdi32体系):窗口、消息、GDI 绘制、DC、区域、光标等; - 内核对象 API(
kernel32体系):swinx/src/sysobjs.cpp(2,381 行)以管道 fd +select()真实实现了事件 / 互斥体 / 信号量 / 可等待定时器 / 定时器队列 / 文件映射,以及WaitForSingleObject/WaitForMultipleObjects等待语义。这意味着既有 Windows 业务代码里基于这些对象的线程同步与等待逻辑可以整体保留,不必改写成另一套线程模型(适用范围与细节差异见 §1.1); - COM / OLE 基础设施:gcc/clang 没有
__uuidof,swinx用guiddef.h的DECLARE_CLASS_SIID生成静态GetIID()并把__uuidof重定义到它(guiddef.h:36-46)、basetyps.h:115-118的DECLARE_INTERFACE_宏集、guiddef.h:69-71的弱符号DEFINE_GUID,连同SUnkImpl<T>(src/SUnkImpl.h:44-82)补齐IUnknown/BSTR(src/objbase.cpp)/VARIANT(src/variant.cpp)/SAFEARRAY(src/safearray.cpp,1,696 行)/IDispatch,让无障碍(ACC)、RichEdit 等依赖 COM 的代码一字不改跨平台编译; - 无障碍(ACC / MSAA)——这是”重演而非空桩”最容易被忽略的硬证据:
swinx/src/oleacc.cpp(768 行)真实实现了AccessibleObjectFromWindow/FromPoint/FromEvent/SetWinEventHook/LresultFromObject等一整套,Linux 侧经 AT-SPI 落地(src/platform/linux/SAtSpi.cpp,2,727 行),macOS 侧经NSAccessibility(src/platform/cocoa/SNsAccessibility.mm,847 行)。把一整套无障碍体系连同平台桥接一起搬到非 Windows,是”宽度 + 保真”最难被模仿的一段。
窗口创建按平台能力分两条路径落地——这是 swinx 把 Win32 窗口语义”重新成立”的两种不同工程选择:
- C++ 可访问窗口系统的桌面端(含 iOS):
swinx内部直接实现窗口创建。 Windows 用系统 Win32;Linux 基于 XCB/X11 自建窗口系统(src/platform/linux/SConnection.cpp:1455xcb_create_window_checked);macOS / iOS 经 Cocoa / UIKit 桥接(SNsWindowHost : NSWindowSNsWindow.mm:363、[[UIWindow alloc] initWithFrame:]SUIWindow.mm:917)——这些平台的 C++(或 Objective-C)一侧本身具备创建原生窗口的能力,swinx在兼容层内部直接把它重演成CreateWindowEx语义,无需宿主 App 额外补窗口能力。 - C++ 不可访问窗口系统的移动端(Android / OHOS):经外接
g_platformAPI接口补齐。 这两类平台的 C++ 运行时不具备直接创建窗口的能力,窗口由宿主 App 的 Java / ArkTS 侧持有。于是swinx抽象出一套回调结构体(platform_api.h,PlatformAPI_Init,覆盖 Window/IME/Clipboard/Audio/Path/Shell),由宿主 App 补上窗口 / 输入 / 剪贴板 / 提示音等原生能力(消费侧src/platform/mobile/SConnection.cpp:1147-1160,该文件共 51 处g_platformAPI引用)——这是 Android/OHOS 在不修改框架主体的前提下接入的契约护栏。
两条路径的共同结果:无论窗口由swinx内部创建、还是由宿主经platform_api回调提供,向上暴露的都是同一套 Win32 窗口消息语义(内核SMsgLoop归一),业务代码对此无感知、无分支。
“重演 Win32”最极端的两处佐证——把整个 Windows 组件搬上岸:
- Scintilla 的 Win32 前端被整体搬到所有平台:
third-part/Scintilla/CMakeLists.txt:11用GLOB_RECURSE全平台收录win32/(:19-DSTATIC_BUILD -DSCI_LEXER,无PLAT_GTK,win32 前端是唯一前端),非 Windows 时add_dependencies(Scintilla swinx)(:24-27)。搬过来的是ScintillaWin.cxx(3,923 行,自称 “Windows specific subclass”)+PlatWin.cxx(3,249 行)+HanjaDic.cxx= 7,302 行纯 Win32 前端代码,语法着色 / 代码折叠全部走SendMessage(SCI_*)协议。 - RichEdit41 被整体搬运:
third-part/richedit41133 个源文件 / 48,175 行,Linux 上编为libmsftedit.so、macOS 上为libmsftedit.dylib,由SOUI/src/control/SRichEdit.cpp:99-104LoadLibrary+GetProcAddress("CreateTextServices")装载;SOUI 侧共 26 个文件引用 msftedit 符号。
兼容层的代码来源构成(主动披露):swinx/src与swinx/include中有 9 个文件源自 Wine 的对应实现(include/winerror.h、cursoricon.cpp、safearray.cpp、profile.cpp、malloc_impl.cpp、cmnctl32/listbox.cpp、uitools.cpp、list.h、cmnctl32/heap.h),其余全部为自研;该批文件的著作权与许可状况已在license_CN.txt/license_EN.txt中逐项披露。此外thirdparty/下约 7,800 个 vendor 文件(换取构建可复现与零版本兼容风险,其代价见 §5.6)——兼容层”重演 Win32”的主体是自研代码,Wine 派生与 vendor 依赖的边界清楚且已披露。
抽掉支柱一会怎样:没有这层兼容层,”同一套 C++ 跑六端”不成立,§1 的全部论证失去地基;而且注意,没有它,支柱三也塌——SOUI 的 DirectUI 框架本身就是建立在 Win32 消息 / GDI 语义之上的,兼容层是它的运行基座(见 §2.4”框架与兼容层协同设计”)。
2.3 支柱二:平台 × 渲染二维正交(回答”可扩展性”)
*.cmake 用 file(GLOB) 自动纳入当前平台源文件,新增 .cpp/.mm 不需改 cmake:
| 目标平台 | 平台适配层 | 渲染后端 | 平台专有依赖 |
|---|---|---|---|
| Windows | (不编译 swinx,用系统 Win32) | GDI / D2D | Win32 SDK |
| Linux(桌面) | platform/linux | gdi/cairo | ALSA(可选)、xcb / xkbcommon / dbus |
| macOS | platform/cocoa | gdi/apple | Cocoa / CoreGraphics / CoreServices |
| iOS | platform/ios | gdi/apple | UIKit |
| Android | platform/mobile | gdi/cairo | Android NDK(JNI) |
| OpenHarmony | platform/mobile | gdi/cairo | OHOS NDK(napi / native_window) |
凭什么答”可扩展性”——把”加平台”从乘法压成加法。 platform/*(窗口壳 / 事件循环 / 剪贴板 / IME / 拖放 / DPI)与 gdi/*(绘制)是两个正交维度:Linux 与 Android/OHOS 复用 Cairo 渲染而平台层不同,macOS 与 iOS 复用 CoreGraphics 而平台层不同。于是:
- 新增一个平台 = 写一份
platform/目录 + 复用已有某个gdi/后端; - 新增一个渲染后端 = 写一份
gdi/目录,所有平台自动获得。
两者互不牵连——平台数是加法,渲染后端数也是加法,而不是 N 平台 × M 后端的乘法。 这正是”六端”能站得住的真正原因:它不是六个一次性搬运的特例,而是一套能持续吸收新平台的架构。
这一设计的价值是”平台可扩展性”,而非”当前恰好覆盖了六端”——判据是一个正在进行时的反证:FreeRTOS。 git branch -a 显示 freertos 分支已在本地与 origin 开发中:一个没有传统桌面窗口系统的嵌入式 RTOS 场景,它只需新增一个 platform/ 适配、复用现有渲染后端,即可把同一套 UI 框架带过去,而不必重构现有架构。一个分支的存在,比任何架构图都更能证明这条轴是真的。
这里也解释了为什么 SOUI5 没有 Qt 那类”双 UI 线程”负担:UI 直接运行在平台原生线程上,窗口消息由platform/*归一为 Win32 消息循环语义(内核SMsgLoop,§2.5),与系统 UI 的交互就是在原生线程上的常规消息处理。
抽掉支柱二会怎样:兼容层(支柱一)能让代码在六端跑起来,但每加一端都要动一遍渲染、每加一个渲染后端都要在 N 个平台各改一遍——”六端”会被锁死在今天这份清单里,框架随平台演进的边际成本趋近乘法。支柱二保证的是这套方案随时间继续有效,而不只是此刻有效。
2.4 支柱三:SOUI 高性能 UI 快速开发框架(回答”可开发性 / 可维护性”)
这是最容易被当成”兼容层上的附带好处”、因而最需要说清”为什么它本身是一根支柱”的一节。
先回答”为什么框架是一根支柱,而不是附带好处”——因为本方案最核心的价值主张,有一半压在它身上。 信创迁移的工作量可以拆成两项:重写 UI 的成本 + 改写业务逻辑的成本。支柱一(保留 Win32 逻辑)只解决了后半;前半——UI 不重写、而是声明式重述——完全依赖支柱三。如果没有支柱三,迁过去的是”一份能跑但难以维护的旧界面代码”:信创客户拿到手的不是资产延续,而是技术债平移。支柱三的作用,是把支柱一换来的”可移植”兑现为”可长期维护、可持续演进的资产”——它是这套方案从”能跑”走向”可用、敢用”的那一极。
再回答”为什么偏偏是 SOUI 的框架”——因为它与兼容层是协同设计的,而不是”随便某套 UI 框架下面垫一个 Win32 shim”。 正因为支柱一完整保留了 Win32 的消息 / GDI / 内核对象语义,SOUI 的 DirectUI 框架(消息循环、控件树、皮肤、绘制、动画)本身就是跨六端一致的——同一套控件、同一份 XML、同一套动画,在六端上是同一件事。这种”框架即跨平台”是”在任意框架下外挂一个 Win32 兼容层”(或反过来)得不到的:兼容层重演的语义与框架依赖的语义在这里是同一套。
它由六个相互支撑的部分构成。不要把下面六项当成功能清单——每一项都对应一类”每平台 / 每项目重复劳动”的消灭:
- 类 COM 引用计数内存模型:
IObjRef→TObjRefImpl<T>→SAutoRefPtr<T>三级结构(utilities/include/interface/obj-ref-i.h:18、utilities/include/helper/obj-ref-impl.hpp:13-269,AddRef/Release走InterlockedIncrement/InterlockedDecrement),皮肤(SSkinObjBase)、字体池(SFontPool)、位图(IBitmapS)、渐变、事件参数(SEvtArgs)等资源对象以引用计数管理,订阅即增引用、回调期间对象不会悬空;控件树刻意用裸指针 + owner 语义(SWindow父子/兄弟链表为裸指针,SWnd.cpp:1005-1017销毁时Release()移交所有权)避开父子循环引用。它消灭的是 C++ GUI 最高频的一类坑——事件回调期资源已被释放 / 资源池生命周期失控。 口径须如实:这套机制降低的是特定类别风险(忘记Release()、循环引用),不是“消除 C++ 内存问题”。 - XML 布局语言 + 对象工厂:控件树 / 属性 / 皮肤 / 布局用声明式 XML 描述,
SObjectFactory把节点名映射到类(SOUI/include/core/SObjectFactory.h:79-142),内置注册 58 个窗口类 / 13 个皮肤类(SOUI/src/SApp.cpp:135-218),属性系统有 43 个ATTR_*宏(SOUI/include/helper/SAttrCracker.h)、100 处SOUI_MSG_MAP_BEGIN使用。它消灭的是”改界面就要动业务代码”——UI 与逻辑分离,这也是 §4.2 迁移方法学能把”重写”变”重述”的关键杠杆;C++(SOUI_MSG_MAP/ 事件订阅SNotifyCenter)承载逻辑层,Lua(ScriptModule-LUA)承载快速迭代 / 原型 / 热更新。 - 基于
ISkinObj的皮肤(渲染)抽象——”UI 自由组合”的地基:一切可视化表现收敛到同一个绘制接口ISkinObj(SOUI/include/interface/SSkinobj-i.h:28,DECLARE_INTERFACE_(ISkinObj, IObject)):核心入口DrawByState2(CTHIS_ IRenderTarget *pRT, LPCRECT rcDraw, DWORD dwState, BYTE byAlpha)(同文件:41-42),辅以DrawByState/DrawByIndex2/DrawByIndex(按状态 / 索引绘制)、GetSkinSize/GetStates(尺寸与状态数)、GetAlpha/SetAlpha、OnColorize(整体换色)、GetScale/SetScale/Scale(DPI 缩放)。其基类SSkinObjBase : public TObjRefImpl<SObjectImpl<ISkinObj>>(SOUI/include/core/SSkinObjBase.h:77)——每个皮肤同时是 COM 引用计数对象与可被 XML 描述的对象:SSkinPool::_LoadSkin(SOUI/src/res.mgr/SSkinPool.cpp:72-82)按 XMLtype属性经对象工厂创建并进入皮肤池,内置注册 13 个皮肤类(SOUI/src/SApp.cpp:202-217:帧序列图imglist、居中图imgcenter、边框拉伸图imgframe/imgframe2、按钮态button、渐变gradation/gradation2、滚动条scrollbar、纯色块colorrect、矢量形状shape、多状态组合group/group2、树连接线treelines),控件侧经SetSkin(ISkinObj*)(SOUI/include/interface/SCtrls-i.h:225)以SAutoRefPtr<ISkinObj>持有。它换来两个解耦:① 控件只认识”在什么状态下、把皮肤画到渲染目标的哪块矩形上”(SCmnCtrl.cpp:417-424等处只传WndState_Normal/WndState_Hover),完全不关心背后是图片、渐变、形状还是组合——换肤只改 XML 里的皮肤名,控件代码零改动;②DrawByState2的第一个参数是IRenderTarget,皮肤只面向渲染抽象绘制、不碰任何平台 API——这正是支柱二”平台 × 渲染正交”在应用框架侧的落地,同一份皮肤描述在六端各渲染后端上一致。它消灭的是”换表现就要动控件代码、每种绘制各写一套”——皮肤可独立替换、可整体换主题、可按需扩展(再实现一个ISkinObj子类注册进工厂即可,框架层零改动);有了这层抽象,后面的 XML 自由组合、换肤体系与控件外观定制才成立。 - 时间轴动画引擎 + 三套动画方案:以
ITimelineHandler组织(SOUI/include/interface/STimelineHandler-i.h:14),提供窗口动画(IAnimation/SAnimation)、数值动画(IValueAnimator/SValueAnimator,内置 7 个:SInt/SByte/SSize/SPoint/SRect/SFloat/SColor)、属性动画(IPropertyAnimator/SPropertyAnimator,注释自陈 modeled after AndroidObjectAnimator)三套方案,覆盖绝大多数交互动效。关键工程设计是”所有动画共用一个统一脉冲定时器”:kPulseTimer(SHostWnd.h:296)+kPulseInterval = 10ms(STimelineHandler-i.h:19)在有动画时才创建、无动画即销毁(SHostWnd::OnTimelineRequestChangedshostwnd.cpp:1523-1533),每帧由STimerlineHandlerMgr::OnNextFrame(STimerlineHandlerMgr.cpp:53-86)一次遍历全部 handler 与 animator、当帧合并刷新请求,由宿主窗口统一重绘一次——它消灭的是”多个动画各自触发刷新造成的重复重绘与效率浪费”,让现代交互动效在六端一致且不拖性能。其中SAnimationSet是IAnimation的组合实现(多个窗口动画序列/并行)、SAnimatorSet/IAnimatorSet是IValueAnimator的组合实现(多数值动画按AnimatorNode依赖编排,SEQUENCE/PARALLEL),二者均遵循 AndroidAnimatorSet设计。 - 基于
ILayout的灵活布局:布局与布局参数成对注册(ILayout+ILayoutParam,SOUI/include/interface/slayout-i.h:58/145)。SOUI/include/layout/已内置 6 组(SouiLayout/SLinearLayout/SGridLayout/SFlowLayout/SFrameLayout/SAnchorLayout,SOUI/src/SApp.cpp:219-231注册 10 个布局参数工厂项)——它们覆盖了线性、网格、流式、锚点、层叠与绝对定位等几乎所有常规开发会遇到的基础布局原型,绝大多数界面需求都能用内置布局直接满足。它消灭的是”一套 UI 在手机 / 平板 / 桌面 / 高 DPI 各写一份”;而当遇到非常规特例时,也只需自行实现一对ILayout+ILayoutParam即可追加新布局,框架层无需任何改动——扩展在应用侧完成,不侵入内核。 - 多套 MVC 虚拟列表控件 + 完整控件系统:核心 40 个控件头 / 54 个
DEF_SOBJECT/ 58 个注册窗口类,扩展控件库controls.extend53 个控件类;以 MVC 模式提供虚拟列表族(SListView/SMcListView/STreeView/STileView/SComboView,适配器ILvAdapter/IMcAdapter/ITvAdapter在SOUI/include/interface/SAdapter-i.h),以数据适配器驱动、经UpdateVisibleItems只渲染可见项并用品项回收池(m_itemRecycle)复用面板(SOUI/src/control/SListView.cpp:309/362/453)。它消灭的是”大数据列表卡顿”与”重复造控件”两件事。
抽掉支柱三会怎样:你会得到一层能跑的 Win32 兼容层,但每个项目都要自己滚一遍 UI 层——内存模型、皮肤渲染抽象、声明式布局、动画、自适应布局、虚拟列表全得自己来。于是 §1.1/§3.1”迁移工作量中低”的承诺失去一半依据(UI 那一半),也没有任何东西把 SOUI 与”能产出原生构建的 Wine”区分开。支柱三不是兼容层的装饰,它是这套方案作为”框架”而非”库”的那一极。
2.5 配套机制:异步任务与线程协作
IMessageLoop::PostTask/ITaskLoop::postTask/STaskHelper::post:把工作线程任务投递回 UI 线程执行(内核SMessageLoopSOUI/src/core/SMsgLoop.cpp,主循环MsgWaitForMultipleObjects,异步任务经隐藏消息窗口 +WM_TIMER(TM_POSTTASK=200)泵回 UI 线程),避免跨线程直接操作控件;- Win32 内核对象(§2.2)承载线程同步与等待,
swinx以 fd +select复现其语义; - 事件系统:
SNotifyCenter(SOUI/include/event/SNotifyCenter.h:100)统一分发,FireEventSync/FireEventAsync+ 按IsBubbleUp冒泡,订阅支持自由函数 /std::function/ 成员函数三种 slot(SOUI/include/event/SEventSlot.h)。
一个易踩的坑:SStringT是单线程实现(COW 裸引用计数),跨线程必须换用std::string。
2.6 架构总账
| 资产 | 规模 / 事实 |
|---|---|
| 自有框架源码 | 868 文件 / 323,425 行(内核 SOUI/ 149,310 + utilities/ 35,351 + 16 组件 components/ 86,094 + 扩展控件 controls.extend/ 52,670,排除 vendor) |
| swinx 兼容层 | 225 文件 / 168,472 行;45 头文件中 30 个与 Windows SDK 同名;api_scan 真实实现 894 / 桩 37 |
| 控件 | 核心 40 控件头 / 54 DEF_SOBJECT / 58 注册窗口类 / 13 皮肤;扩展控件 53 个控件类 |
| 内置布局 | 6 组(SouiLayout/SLinearLayout/SGridLayout/SFlowLayout/SFrameLayout/SAnchorLayout) |
| 渲染后端 | 3 个(skia / gdi / d2d),按平台与场景选择;此外 swinx 1.7 新增跨平台 OpenGL(WGL) API,可由 render-skia 承载 OpenGL 上下文(见 demos/opengl_demo) |
| 平台 | 6 端(Windows / Linux / macOS / iOS / Android / OHOS),FreeRTOS 在 freertos 分支开发中 |
| 发行体积(内核) | VS2008 x86 /MT,含全部核心控件 = 2,426,880 B(2.31 MiB) |
| 质量门禁 | 427 条无头用例(soui-headless 约 422 条)+ 4 个 CI 工作流 |
三、应用场景
3.1 场景一:信创环境下的 Windows 客户端国产化迁移(核心场景)
这是本方案最核心的场景:政企/金融/工业客户已有成熟 Windows C++ 客户端,需迁到国产 Linux(麒麟/UOS)或鸿蒙。
SOUI5 的路径:UI 层用 XML 声明式重述 + 业务层(尤其基于 Win32 内核对象的同步/等待逻辑)几乎原样保留——将一个”重写几十万行”的工程,压缩为”重述界面 + 局部适配”的工程(§1.1 详述三项能力的适用边界,§4.2 给出方法学)。
3.2 场景二:Qt 国产替换
对已用 Qt 或有 Qt 技能栈的团队,SOUI5 是”授权自主 + 单 UI 线程 + 体积更小”的替换选项:
| 对比项 | SOUI5 | Qt | 说明 |
|---|---|---|---|
| 授权 | 自有条款(个人免费 / 商用收费),不受 LGPL 传染 | LGPL / 商业授权 | 闭源商业产品合规负担更轻 |
| 核心体积 | 2.31 MiB(含全部核心控件、/MT 不依赖 CRT) | 数十 MB | 显著更小,但须按同等配置比较 |
| 移动端线程模型 | 单 UI 线程,原生线程直接跑 UI | 独立 UI 线程(双线程) | SOUI5 无跨线程协调负担 |
| Win32 资产 | 直接复用 | 需面向 Qt API 重写 | 存量迁移场景的关键差异 |
3.3 场景三:鸿蒙(OHOS)原生应用
OHOS 为正式支持平台(非社区补丁):经 PlatformAPI 桥(PLATFORM_API_VERSION = 4,platform_api.h:16,platform_api.cpp:13-19 严格版本校验、不等即拒绝注册;宿主侧 soui-ohos-lib/.../OhosPlatformAPIReg.cpp:193 注册)+ soui-ohos-lib(HAR 包)接入 EntryAbility,已有 games/cnchess 鸿蒙实机案例。
3.4 场景四:一产品多平台代码的统一(取代”每平台一份代码”)
当 Qt 类框架移动端支持有限、项目被迫”每平台一份代码”时,SOUI5 的六端同源(§4.2 零平台宏证据)把多端维护收敛为一份,直接消减”人力翻倍 / 版本漂移 / 缺陷多处修复”(§1.2 对照表)。
3.5 场景五:对帧时序 / 体积敏感的客户端与企业跨平台应用
- 性能一侧(定性论述):无 GC 抖动、可直接控制绘制与帧时序,MVC 虚拟列表只渲染可见项,适合对帧时序有硬约束的场景——量化基准数据尚在建设中,此处不作数值主张;
- 企业应用一侧:多语言热切换、High-DPI 自动缩放、XML 布局的 UI/逻辑分离,适合企业级跨平台应用的长期维护。
3.6 场景六:脚本化快速迭代与原型验证
Lua 内置(ScriptModule-LUA,含 lua_tinker 绑定层)+ 完整示例(test.lua、俄罗斯方块示例),支持控件创建与操作、事件绑定、动画驱动、NativeCall 扩展,适合快速迭代、原型验证与热更新。
边界:Lua 绑定面虽广但并非全 API 覆盖,使用前宜核对 exp_*.h 导出清单。
四、创新点
本方案的技术创新凝练为四条核心(§4.1–§4.4),分别对应路线、工程方法学、架构、资源与分发四个维度,四者互为支撑;每条都按新在哪 / 难在哪 / 硬证据 / 边界展开,力求立得住、经得起核。此外另有一组支撑性工程能力(§4.5),进一步补强框架的可用性、性能与发行弹性。
4.1 创新点一(路线):以”重演 Win32”替代”抽象 Win32”——把兼容层做成资产复用引擎
新在哪:三条跨平台路线里(§1.3),前两条都在”让开发者少学、面向新 API 重写”,第三条(换语言/自绘)连技能栈一起换掉。SOUI5 走的是被前人判定”最难走”的第四条——不抽象、不替换 Windows,而是让 Windows 的 API 面在其它平台上重新成立。这不是实现技巧差异,而是路线前提差异:正因为选择”重演”,”资产复用”才从附带好处变成路线前提(§1.5 表中唯一”能”的那一行)。与最接近的同类思路(Wine 的 winelib 模式)相比,SOUI5 的路线价值在于把”重演”从桌面 Linux 的源码兼容工具推进为覆盖六端(含移动与嵌入式)并附带完整 UI 框架的产品级方案(边界对比见 §1.5)。
难在哪:兼容层的难度不在”能跑几个 Demo”,而在宽度与保真同时成立——
- 宽度:要覆盖 Windows 开发者日常依赖的整类 API,而不只是窗口与绘图。
api_scan实测声明 1,066 个、真实实现 894 个(§2.2),连无障碍(ACC)这种最容易被放弃的体系都连同 AT-SPI / NSAccessibility 桥接一并落地(合计 768+2,727+847 行); - 保真:要让行为也一致,而不只是签名一致。内核对象的等待语义要用 fd +
select复刻(sysobjs.cpp2,381 行);没有__uuidof的编译器上要用宏 + 弱符号把 COM 的IUnknown/BSTR/VARIANT/SAFEARRAY/IDispatch重建出来(§2.2)。
硬证据:swinx 225 文件 / 168,472 行;30 个与 Windows SDK 同名头文件;sysobjs.cpp 2,381 行真实内核对象;ACC 三端桥接 4,300+ 行;Scintilla 的 7,302 行纯 Win32 前端与 RichEdit41 的 133 源文件 / 48,175 行被整体搬到所有平台——”只要组件有 Windows 实现,swinx 就足以让它跨平台,不必为每端另写后端”,这是路线成立的最强佐证;swinx 1.7(2026-10-18)进一步将 OpenGL(WGL)API 纳入跨平台重演(新增 wgl.h 与 demos/opengl_demo 验证),API 面随之扩大。
边界:进程内无名内核对象成熟,跨进程命名对象需评估;.rc 资源层为只读(Begin/End/UpdateResource 显式返回 ERROR_CALL_NOT_IMPLEMENTED);把”任意 Win32 程序零成本直接迁移”所需的迁移面(原生公共控件库 / 窗口菜单栏 / 资源对话框)尚未全部铺齐(§5.6)——这是待补工作量,不是架构不确定性。
4.2 创新点二(工程方法学):”声明式重述 UI + 原样保留 Win32 逻辑”——把重写迁移压缩为重述迁移
新在哪:这项不是某一项全新技术,而是由架构协同产生的一种迁移方法学——它改变了迁移的计价单位:从 Qt 式的”按行重写业务 + 按控件重写界面”,变为”界面按声明式描述重新表达 + 业务逻辑模块原样保留“。公允地说,声明式 UI、引用计数各自都不新;新的是这套组合被有意识地组织成一条可复用的”存量 Win32 资产 → 六端”迁移路径,且它的两端分别由支柱一(保留 Win32 逻辑)与支柱三(XML 声明式重述)支撑。这也正是支柱三之所以是支柱的落地理由(§2.4)。
难在哪:难在”两端都要成立”——只保留逻辑不重述 UI,得到的是难维护的旧界面;只重述 UI 不保留逻辑,退化成正统重写。SOUI5 让两端同时成立,靠的是兼容层与框架协同设计:同一套 Win32 语义既是旧代码的运行基座,又是新框架(XML + 控件树 + 布局)的表达基座。
硬证据:跨平台样板 games/cnchess 的核心绘制与业务源码中 __ANDROID__ / __OHOS__ 出现次数均为 0(逐文件计数,排除 .cxx 构建产物;业务源码中唯一的平台宏在桌面入口 main.cc 的 __APPLE__,属入口代码而非业务逻辑)——业务开发者写的是一份普通 C++ 代码,六端差异被兼容层与薄入口吸收,而非散落在业务代码里的 #ifdef。该模式另有特性层的多端复现:仓库 demos/ 下有 20 个 demo / 工具工程,其中 Android / OHOS 各有宿主级 demo(android-demo / ohos-demo),其余为桌面端特性 demo(MVC 列表 / 网格 / 流式 / 帧布局 / HiDPI / 属性动画 / 图表 / 富文本等)。XML 侧由对象工厂(58 个窗口类按节点名注册)、43 个属性宏、6 组内置布局 + MVC 虚拟列表承接”重述”。
边界:口径须如实——”完整业务样板零平台宏”的实测样本当前为 1 个(games/cnchess,覆盖六端构建),20 个特性 demo 提供的是特性级复现(跨端的主要是 Android / OHOS 宿主 demo,其余为桌面 demo)。它强有力地证明了该模式可行,但不能外推为”所有业务代码都能零平台宏”;不同业务对平台专有能力的依赖程度不同,选型时应结合自身业务评估。
4.3 创新点三(架构):平台 × 渲染二维正交 + 版本化 PlatformAPI 契约——让”加平台”成为加法而非乘法
新在哪:多数框架的平台抽象是”一维”的——平台与渲染往往被绑在一起处理,加一个平台或换一个渲染后端都可能牵动全局。SOUI5 把平台适配(platform/)与渲染后端(gdi/)拆成两个正交维度(§2.3),并用一套版本化契约(g_platformAPI / PLATFORM_API_VERSION = 4)处理”宿主能力外接”这一跨平台里最脏的问题——移动端窗口由 Java/ArkTS 持有,框架不侵入宿主、宿主也不改框架,仅通过一个严格版本校验(不等即拒绝注册,platform_api.cpp:13-19)的回调结构体对接。正交拆分 + 契约护栏两件事合起来,才让”加平台”稳定地成为加法。
难在哪:正交不是画图分目录,而是要保证任取一个平台 × 任取一个后端都能组合且行为一致;契约护栏则要在”框架需要的能力”与”宿主能提供的能力”之间划出稳定边界,并用版本号把破坏性变更挡在门外(v3→v4 的演进即靠此机制)。
硬证据:platform/(linux / cocoa / ios / mobile)与 gdi/(cairo / apple)当前组合出六端,新增 .cpp/.mm 由 file(GLOB) 自动纳入、不改 cmake;freertos 分支已在开发中(本地 + origin),它只需新增一个 platform/ 适配即可把一个”无传统桌面窗口系统”的 RTOS 场景纳入同一框架——这是”正交轴真实存在”的进行时反证;移动端 SConnection.cpp 有 51 处 g_platformAPI 引用,Android/OHOS 两个宿主分别注册。
边界:正交降低的是”加平台”的边际成本,不等于零成本——新平台仍可能要处理其专有的输入法 / 剪贴板 / 生命周期语义。
4.4 创新点四(资源与分发):全桌面平台 .rc 跨平台编译 + 运行时资源解析 + 单文件分发
新在哪:SOUI5 把 Windows 开发者最熟悉、生态沉淀数十年的资源文件(.rc)做成了跨桌面平台的统一资源编译—解析—分发机制。这不是”另造一套资源格式”,而是让 .rc 这一既有资产在 Linux / macOS 上继续有效,且发布物收敛为单个可执行文件。
其一,.rc 的跨平台编译。 Windows 上由系统原生编译;Linux / macOS 上借助 MinGW 的 windres 把 .rc 编成 COFF,再链接进最终产物——Linux 走 ld -r -b binary 转 ELF 并用 nm+objcopy --redefine-syms 固定符号前缀(__cmake/windres.cmake:192-221),macOS 走 .incbin 汇编生成 Mach-O(:159-184),三端同源(PE / ELF / Mach-O)。
其二,运行时资源解析,让非 Windows 平台像 Windows 一样读资源。 swinx/src/resapi.cpp 提供与 Windows 一致的资源 API(FindResource / LoadResource / LockResource / SizeofResource / EnumResource* / LoadString,:131-427);swinx/src/coffparser.cpp 的 WindResResourceParser 在运行时解析嵌入的 COFF 资源段,按 Windows 的”类型-名称-语言”三级目录递归定位资源数据(coffparser.h:118 三级 map,ParseResourceDirectory :100-204 深度上限 3)。上层代码无需改动,即可在非 Windows 平台以同一套 FindResource/LoadResource 语义取资源。
收益一:兼容传统 Windows 项目的开发习惯(对话框资源)。 图标 ICON、字符串表 STRINGTABLE、版本信息自不必说,对话框的 DIALOG / DIALOGEX 模板也直接写在 .rc 里,可由 Visual Studio 资源编辑器可视化设计、由 CreateDialog / DialogBox 系列在运行时实例化。因为 SOUI5 直接复用同一套 .rc,现有 Windows 项目迁往 Linux / macOS 时,不必把对话框模板与整套资源改写成另一种格式——传统 Win32 开发者的工作方式与既有资源资产都能原样延续,迁移阻力被显著拉低。
收益二:跨平台单文件分发。 资源在编译期嵌入可执行文件,运行时经 SResProviderPE(SOUI/src/res.mgr/SResProvider.cpp:54)直接从资源段创建 UI——无需额外的资源目录或配置文件,部署与分发简化为”一个可执行文件”。同时开发者继续用熟悉的 Windows 资源编辑工具,跨平台资源开发的学习成本被压到最低。
边界:该机制当前覆盖桌面三端(Windows / Linux / macOS);Android / OHOS 的资源走各自平台原生资源体系(见 §3.3)。资源层为只读实现(resapi.cpp:334-389Begin/End/UpdateResource显式返回ERROR_CALL_NOT_IMPLEMENTED)。
4.5 支撑性工程能力
在四条核心创新之上,以下工程能力进一步补强框架的可用性、性能与发行弹性:
- 时间轴动画引擎(三套动画 + 统一脉冲定时器合并刷新):以
ITimelineHandler组织,提供IAnimation/IValueAnimator/IPropertyAnimator三套动画,并由统一脉冲定时器当帧合并全部刷新请求、宿主窗口统一重绘一次(详见 §2.4);SAnimationSet/SAnimatorSet分别用于组合多个窗口动画与编排多个数值动画。 - SVG 作为低成本 HiDPI 方案(
cacheSvg按目标尺寸光栅化缓存):SSkin.h:248默认开启,SSkin.cpp:355-420按本次渲染尺寸光栅化并缓存、尺寸变化才失效,兼顾矢量分辨率无关与位图渲染效率;定位为 SVG 1.1 静态子集(基于 nanosvg,Svg.cpp:46),明确不支持 SVG 动画 / 交互 / 脚本,将 SVG 稳固定格在渲染原语层。 - 16 组件积木式选型(实测发行体积差约 11 倍):
SAppCfg(SOUI/include/SAppCfg.h:66-424)链式选型 +SComMgr2类 COM 工厂装载(DLL COM 与静态LIB_SOUI_COM两种方式调用代码零差异);体积可裁剪的硬数据见 §5.1。 - Lua 脚本层:内置 Lua 脚本(含 lua_tinker 绑定),支持控件创建与操作、事件绑定、动画驱动与
NativeCall扩展,绑定面广但非全 API 覆盖(见 §3.6 边界)。
五、方案价值总结
| 价值维度 | 具体体现 |
|---|---|
| 对信创 | 已适配 OpenKylin / UOS / deepin;以 OpenKylin 社区上游仓库形态分发;Windows C++ 逻辑资产可整体保留(UI 声明式重述 + Win32 内核对象同步代码保留,方法学见 §4.2) |
| 对鸿蒙 | OHOS 为正式支持平台;soui-ohos-lib HAR 化;已有 cnchess 鸿蒙实机案例;一套代码覆盖桌面 + Android + 鸿蒙(工程化程度仍属早期,§3.3) |
| 对 Qt 替换 | 授权自主(无 LGPL 传染);体积按同配置比较通常更小;单 UI 线程无跨线程协调;Win32 知识资产可复用(生态/工具链为其短板,§7) |
| 对企业 | 六端同源、零平台宏,可取代”每平台一份代码”;已有数十款商业产品验证(见下) |
| 对开发者 | XML + Lua + C++ 三层分工;组件按场景选型(实测发行体积差可达约 11 倍);皮肤/布局/窗口三维可扩展;XML 布局分离 UI 与逻辑;可视化设计器;多语言热切换 + High-DPI 自动缩放 |
| 对开源生态 | 组件化按需装载;Lua 内置脚本 + JS/Python 独立仓库;427 条无头用例与 api_scan 门禁保障工程质量与 API 面不回退 |
存量背书:products.md 记录的真实商业产品(节选)——
| 产品 | 开发商 | 备注 |
|---|---|---|
| 迅游加速器 | 迅游科技 | 购买授权 |
| 恒星播放器 | 冷湖科技(武汉) | 购买授权 |
| 熊猫加速器 | 江苏友趣网络 | 购买授权 |
| 月轮加速器 | 月轮网络科技 | 购买授权 |
| 航信全票通 | 北京航信 | 购买授权 |
| 百度网盘(Windows) | 百度 | 2025年以前版本,最新版本换成Electron |
| 启程输入法 / xmusic / xplayer / AI快寻 | 启程软件 | 作者自研 |
背书的合理口径:上表是项目方维护的落地清单,体现的是”该框架在真实商业产品中有实际使用“;它不是独立第三方审计的结果,产品数量与授权规模请以清单所述为准。其价值在于证明”框架已被生产环境长期使用“,而非”市场占有率”。须切分两层:表中产品均为 Windows 侧(SOUI2/3 时代)用户,证明的是”被迁移的源资产所依赖的框架,在 Windows 侧成熟可靠“;跨端侧的落地证据另见 §5.4(六端证据分层)——二者共同构成”迁移源质量高 + 迁移目标已跑通“的完整证据链,不应互相顶替。
5.1 积木式选型的发行体积实测
框架的每一个横向能力都是一个独立链接的组件(components/ 下 16 个带 CMakeLists.txt 的独立 target),项目可按目标场景挑选要哪几块,选型结果同时决定”能做到什么”和”发行包有多大”。选型集中在一处——SAppCfg(SOUI/include/SAppCfg.h:66-424):
SAppCfg().SetRender(Render_Gdi) // 渲染后端:Gdi / Skia / D2d 三选一
.SetImgDecoder(ImgDecoder_Stb) // 图像解码:Stb / Wic / Gdip 三选一
.SetAppResZip(_T("uires.zip")) // 资源提供:Zip / 7z / Pe / File 任选
.SetLog(FALSE) // 不要日志 → 不链入 log4z
.EnableMultiLang(_T("lang:lang_cn"), FALSE) // 不要多语言 → 不链入 translator
.EnableScript(FALSE); // 不要脚本 → 不链入 Lua
口径:out/vs2008_x86/bin/Release/(VS2008 x86、/MT静态 CRT、Release),即正常发行场景;逐字节stat实测。CRT 方式核对自out/vs2008_x86/SOUI/soui4.vcproj:94RuntimeLibrary="0"。
| 组件(Release DLL) | 实测字节 | 为什么差这么多 |
|---|---|---|
| soui4.dll(内核,含全部核心控件) | 2,426,880 | 框架主体;/MT 已内含 CRT,不额外依赖 VC 运行库 |
| render-skia.dll | 1,652,736 | 静态链入 Skia 引擎 |
| scriptmodule-lua.dll | 852,480 | 含 Lua 5.4 |
| imgdecoder-stb.dll | 339,968 | 含 WebP 解码 |
| utilities4.dll | 256,000 | |
| log4z.dll | 181,760 | |
| render-d2d.dll | 169,984 | 仅链系统 d2d1 / dwrite,不捆绑引擎 |
| render-gdi.dll | 147,968 | 仅链系统 msimg32 / gdiplus(Linux 下为 swinx+Cairo),不捆绑引擎 |
| resprovider-zip.dll | 104,448 | |
| translator.dll | 62,464 |
结论:体积的决定因素不是组件源码行数的多少,而是”是否在运行时静态捆绑一套渲染引擎”。render-gdi 直接借用系统 GDI / Cairo,产出的 DLL 仅 147,968 B;而 render-skia 自带一整套 Skia,产出 1,652,736 B——相差约 11 倍。
因此,选型直接换体积:一个小程序只要基础功能、不在意渲染特性,选Render_Gdi就能把渲染这一块的发行体积从约 1.6 MB 压到约 0.14 MB;反之,需要复杂图形 / 动画 / 跨端像素级一致性时才值得付出 Skia 的体积。同理,不要日志 / 多语言 / 脚本时,log4z/translator/scriptmodule-lua根本不会进包。这也是”核心约 2.3 MB、按需装载“这一发行特性的直接来源(§0、§2.6)。
选型不影响业务代码的三个保证:同类可替换 = 无锁定(换渲染器只换链接的积木 +SetRender的一个枚举值,业务绘制代码与 XML 不动);COM 形态 = 零侵入集成(SComMgr2静态 COM 与 DLL COM 两种链接方式下调用代码零差异);边界清楚 = 可独立演进(每个组件自带CMakeLists.txt,可在不触碰内核的前提下独立升级)。
5.2 皮肤 / 布局 / 窗口三维扩展,XML 描述布局达成 UI 与逻辑分离
控件的皮肤、布局、窗口本体三者都是开放的可扩展点(SApplication 三个注册模板入口):
| 可扩展维度 | 机制 | 扩展成本 | 源码证据 |
|---|---|---|---|
| 皮肤(Skin) | 皮肤类型经工厂注册,XML <skin type="..."> 按类型名实例化 | 新增一种皮肤 = 派生 SSkinObjBase + 注册类名 | SOUI/src/core/SSkin.cpp:285("svg" 等类型分派);13 个内置皮肤类(SApp.cpp:202-218) |
| 布局(Layout) | 布局与布局参数成对注册,layout="xxx" 即选中 | 新增一种布局 = 实现 ILayout + ILayoutParam 各一 | SOUI/include/layout/ 已有 6 组(SouiLayout/SLinearLayout/SGridLayout/SFlowLayout/SFrameLayout/SAnchorLayout),XML layout 属性经 SWindow::OnAttrLayout(Swnd.cpp:4170-4178)选中,可继续追加 |
| 窗口(Window) | 窗口类经 RegisterWindowClass<T>() 注册,XML 节点名即类名 | 新增一种窗口 = 派生窗口类 + 注册 | 58 个内置窗口类(SApp.cpp:135-199);games/cnchess 的 DEF_SOBJECT(SWindow, L"chessboard") 即例证 |
布局覆盖度:上表”布局”一行列出的 6 组内置布局,已覆盖线性 / 网格 / 流式 / 锚点 / 层叠 / 绝对定位等几乎所有常规界面布局需求,绝大多数实际项目都能用内置布局直接满足;当遇到特殊场景时,只需在应用侧实现一对ILayout+ILayoutParam即可追加新布局,框架内核无需任何改动——这正是 SOUI 布局系统”可无限扩展却从不侵入框架”的设计目标。
XML 的价值落在”UI 与逻辑分离”:控件树的拓扑与属性用声明式表达,配合对象工厂(节点名 → 类)、模板复用与可视化设计器(uieditor)+ 皮肤热换,使改界面不触碰业务代码成为常规工作方式。
5.3 质量保障
工程质量是上述所有能力可信的基础,主要门禁如下:
| 门禁 | 内容 |
|---|---|
| build.yml | push tag / build-test 分支:Windows/Linux/macOS × x64/x86/arm64 全量构建 + 跑 soui-headless + 上传制品 |
| pr-core.yml | PR → master:linux-x64 / windows-x64 / macos-arm64 只构建 fun_test + 跑门禁(失败用 gdb 打印可疑用例栈) |
| gui-smoke.yml | Linux Xvfb:真实宿主窗口烟测(验证鼠标消息到按钮事件派发) |
| swinx-api-gate.yml | python swinx/doc/tools/api_scan.py --check(约 2 分钟,无需编译):断言 swinx 声明的 Win32 API 面与已提交快照一致,动了实现未刷新清单则失败 |
427 条无头 TEST(其中门禁标签 soui-headless 约 422 条)覆盖 swinx/utilities 单元测试、SOUI 核心函数、ZIP 资源提供器集成测试、资源索引与 XML 到控件树的无窗口 E2E;列表族多选/框选由单套件 37 条用例锁定全部交互语义。
该保障的覆盖边界:soui-headless覆盖的是无窗口逻辑层(swinx/utilities/内核函数/资源/XML→控件树);真实 GUI 交互的自动化覆盖有限(gui-smoke.yml仅一项 Linux Xvfb 烟测),且移动端(iOS / Android / OHOS)尚无 CI 自动构建与回归。这是”工程质量可信”的实际范围,不应被读作”全平台全场景已自动化验证”。各端证据强度的分层清点见 §5.4。
5.4 六端落地证据分层
“六端原生”不是一句口号,但各端证据强度并不相同——与其混为一句,不如分层清点(验证方式均可用仓库当前源码复现):
| 平台 | 自动化证据 | 业务 / 演示级样例 | 证据强度 |
|---|---|---|---|
| Windows | build.yml 全量构建 + 427 条无头用例 | demos/ 全部 20 个工程;迅游 / 恒星 / 百度网盘等存量商业产品(Windows 侧,见上表) | 最强 |
| Linux | build.yml linux-x64 / arm64 全量构建 + soui-headless + gui-smoke(Xvfb 真实窗口烟测) | OpenKylin / UOS / deepin 适配,以 OpenKylin 社区上游仓库形态分发 | 强 |
| macOS | build.yml macos-x64 / arm64 全量构建 | games/cnchess 的 macOS 工程(CMakeLists.txt APPLE 分支含代码签名配置、icon.icns) | 中(无第三方业务样例) |
| Android | 无 CI(移动端尚无自动构建,§5.3) | games/cnchess Android 入口(http://android_entry.cc)+ demos/android-demo 宿主 | 中(本地构建 + 实机) |
| OpenHarmony | 无 CI | games/cnchess OHOS 入口(http://ohos_entry.cc)+ demos/ohos-demo + soui-ohos-lib(HAR)接入 EntryAbility,有实机案例 | 中(实机案例) |
| iOS | 无 CI、无 demo 工程 | 平台适配在库(swinx platform/ios + UIKit 桥接),缺端到端业务样例 | 最弱(待补端到端样例) |
分层的意义:桌面三端有 CI 与样例闭环,证据最强;移动三端以”本地构建 + 实机 demo”为主,iOS 目前只有框架内适配。本节按端列清证据强度,是为了让”六端原生”成为一个逐端可查、强度分明的事实陈述;移动端 CI 与 iOS 端到端样例是明确的后续补强项(§5.6)。
5.5 开源社区健康度与授权条款
| 维度 | 事实(2026-10-18 实测) |
|---|---|
| 贡献者 | 47 位(git shortlog -sn --all;提交集中度较高的现实见 §5.6) |
| 提交总量 | 2,909 次(git rev-list --count --all) |
| 版本发布 | 24 个 tag,最新 5.3.2.1(即当前技术基线) |
| 质量门禁 | 4 条 GitHub Actions 工作流(构建矩阵 / PR 门禁 / GUI 烟测 / API 面门禁,见 §5.3) |
| 授权 | SOUI 3+ License:个人免费(个人商用收费)、公司收费(联系作者);历史提交者、被接受的 PR 累计 ≥500 行、soui-demo 投稿者自动获得终身免费授权;社区渠道:QQ 群 229313785 / 385438344 |
| 第三方合规 | license_CN.txt / license_EN.txt 逐项披露第三方与派生代码(含 swinx 中 9 个 Wine 派生文件,§2.2) |
对信创集成的含义:授权条款书面化(个人 / 公司 / 贡献者三档),国产 OS 厂商与集成商可按条款评估;无 LGPL 传染、无国外供应链依赖(§1.4)。社区规模小于 Qt / Flutter(§7),但门禁与披露机制完备——这是一个”小而严“的开源项目。
5.6 需客观认知的边界
SOUI5 的当前能力边界(不影响本方案主张成立,但应如实说明):
- “0 成本迁移既有 Win32 程序”尚未开箱即用——当前推荐的迁移方式是”用 SOUI5 重写迁移“(UI 声明式重述 + Win32 逻辑保留,§4.2);要让任意既有 Win32 程序直接 0 成本跨端,还需补齐 swinx 的三块”迁移面”(原生控件库 / 窗口菜单栏 / 资源对话框)。需要强调的是:这属于待补齐的工作量,而非架构上的不确定性——支撑该需求的能力(以兼容层重演 Win32 语义、完整 Win32 内核对象支持、并以
platform/与gdi/两个正交维度扩展平台与渲染)已经具备,缺的只是把这三块接口面逐一铺到 swinx 上; - vendor 代码占比较高(换取零版本兼容风险),clone 与检索体验受影响;
- 项目维护集中度较高,持续演进依赖核心贡献者规模扩大。
六、数据溯源
关键数据的出处:
- 源码规模 / 文件数:
find <模块> -name '*.cpp' -o -name '*.h' … -not -path '*/third-part/*' | wc -l+wc -l统计(排除 vendor/third-part);git ls-files | wc -l= 9,409(含 vendor 全量) - swinx 规模 / 同名头文件:
swinx/目录逐文件统计(225 文件 / 168,472 行);同名核对以 Windows SDK 为基准(30 个同名 +gdi.h↔wingdi.h) - swinx 完成度:
swinx/doc/tools/api_scan.py --check(api_scan.json:声明 1,066 / 有定义 937;funcs 分类 impl 894 / stub 37 / partial 6) - 发行体积:
out/vs2008_x86/bin/Release/逐字节stat实测(VS2008 x86、/MT);CRT 方式核对自out/vs2008_x86/SOUI/soui4.vcproj:94RuntimeLibrary="0" - 测试数量:
grep -rhoE '^TEST(_F|_P)?\(' demos/fun_test --include="test_*.cpp" | wc -l= 427(soui-headless门禁标签约 422 条) - 平台宏分布:按
games/cnchess业务源码逐文件计数(排除.cxx构建产物) - 控件 / 布局 / 属性 / 消息映射计数:
DEF_SOBJECT/TplRegisterFactory/ATTR_*/SOUI_MSG_MAP_BEGIN逐处 grep - “15 年”:soui4 的 git 仓库第一次提交是 2018 年,它的第一版是 duiengine,在 2011 年完成;“约 2.3 MB” 则已由 VS2008 x86
/MT发行产物(soui4.dll2,426,880 B,含全部核心控件)实测印证,与自述一致 - FreeRTOS 分支:
git branch -a(本地freertos+remotes/origin/freertos) - 社区与发布:
git shortlog -sn --all | wc -l= 47(贡献者)、git rev-list --count --all= 2,909(提交)、git tag | wc -l= 24(tag,最新5.3.2.1) - swinx 启动时间:
git log --diff-filter=A --format=%ad --date=short -- swinx(首提交 2024-11-28) - CI 矩阵:
.github/workflows/build.yml(Windows / Linux / macOS × x64 / x86 / arm64) - 六端证据分层 / demo 计数:
ls demos/(20 个工程,含android-demo/ohos-demo);games/cnchess/client/CMakeLists.txtAPPLE分支(macOS 工程);平台宏按业务源码逐文件计数(排除.cxx) - 授权条款:
LICENSE-zh.md/LICENSE-en.md(SOUI 3+ License)
七、SOUI5 与 Qt / Flutter 的选型自述
本章从选型视角,对 SOUI5 与 Qt / Flutter 做一次客观自述——不夸大其能力,也不回避其短板:
方案的总体立场:SOUI5 是一个在”存量 Win32 资产迁移 / 六端统一”这一特定场景上具备真实、可验证工程能力的框架;但它在生态、文档、工具链、社区规模上均弱于 Qt / Flutter 等主流方案——而 Qt、Flutter 均为国外项目。
两类选型语境的取舍逻辑并不相同,不宜用同一把尺子衡量:
- 一般商业产品:选框架通常先看”受众范围 / 生态成熟度”,这一点 Qt、Flutter 确实领先,SOUI5 不占优;
- 软件国产化 / 信创需求:首要问题不是”谁生态更大”,而是”能不能用“——即框架是否自主可控、在国产软硬件栈上能否稳定落地、是否受国外供应链或授权条款制约。Qt 的 LGPL / 商业授权、Flutter 由 Google 主导,二者在”自主可控”这一国产化硬约束上本身就需要额外评估;SOUI5 的国产属性与授权自主,回应的是”能不能用”这一前置问题,而非去比拼生态规模。
因此选择 SOUI5,在一般商业语境下是”以资产复用换生态成熟度”的交易(是否划算取决于 C++ 存量与迁移预算);在国产化语境下则是”先确保能用、再谈体验与生态”的前提性选择——其劣势(生态小)在后一语境下并不构成否决项,而其优势(国产、自主授权、六端原生、Win32 资产可复用)恰是落地的前置条件。这笔权衡是否成立,取决于项目所处的具体语境,而非框架本身的绝对优劣。

浙公网安备 33010602011771号