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++ 程序。

这些程序的资产结构有三个特征:

  1. 业务逻辑与 UI 高度耦合:界面代码、交互逻辑、业务规则混在几十万行 C++ 里;
  2. 深度依赖 Win32:窗口消息、GDI 绘制、COM 组件、内核对象、公共控件贯穿全局;
  3. 迁移预算有限:不可能为一个已有产品重新招团队、换语言、从头写一遍。

把这些资产迁到国产 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 框架 可开发性 / 可维护性:代码在六端都跑起来之后,界面能不能被高效搭出来、长期维护下去? 迁过去的是"一份能跑但难以维护的旧界面代码",信创客户拿到的是技术债平移,而非资产延续

一句话概括三根支柱的分工:支柱一让"平台"消失,支柱二让"扩展"变成加法,支柱三让"开发"回归日常。 它们对应"能不能跑 / 能不能一直跑到更多地方 / 跑起来之后好不好用"三把不同的尺子------这正是"三根支柱才具有稳定性"的原因:两根只能覆盖其中两问,必然在第三问上留下塌方。

text 复制代码
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 窗口语义"重新成立"的两种不同工程选择:

  1. C++ 可访问窗口系统的桌面端(含 iOS):swinx 内部直接实现窗口创建。 Windows 用系统 Win32;Linux 基于 XCB/X11 自建窗口系统(src/platform/linux/SConnection.cpp:1455``xcb_create_window_checked);macOS / iOS 经 Cocoa / UIKit 桥接(SNsWindowHost : NSWindow``SNsWindow.mm:363、[[UIWindow alloc] initWithFrame:]``SUIWindow.mm:917)------这些平台的 C++(或 Objective-C)一侧本身具备创建原生窗口的能力,swinx 在兼容层内部直接把它重演成 CreateWindowEx 语义,无需宿主 App 额外补窗口能力。
  2. 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-104``LoadLibrary + 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)按 XML type 属性经对象工厂创建并进入皮肤池,内置注册 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 Android ObjectAnimator)三套方案,覆盖绝大多数交互动效。关键工程设计是"所有动画共用一个统一脉冲定时器":kPulseTimer(SHostWnd.h:296)+ kPulseInterval = 10ms(STimelineHandler-i.h:19)在有动画时才创建、无动画即销毁(SHostWnd::OnTimelineRequestChanged``shostwnd.cpp:1523-1533),每帧由 STimerlineHandlerMgr::OnNextFrame(STimerlineHandlerMgr.cpp:53-86)一次遍历全部 handler 与 animator、当帧合并刷新请求,由宿主窗口统一重绘一次------它消灭的是"多个动画各自触发刷新造成的重复重绘与效率浪费",让现代交互动效在六端一致且不拖性能。其中 SAnimationSet 是 IAnimation 的组合实现(多个窗口动画序列/并行)、SAnimatorSet/IAnimatorSet 是 IValueAnimator 的组合实现(多数值动画按 AnimatorNode 依赖编排,SEQUENCE/PARALLEL),二者均遵循 Android AnimatorSet 设计。
  • 基于 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 线程执行(内核 SMessageLoop``SOUI/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.cpp 2,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-389 Begin/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):

cpp 复制代码
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:94 RuntimeLibrary="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 的当前能力边界(不影响本方案主张成立,但应如实说明):

  1. "0 成本迁移既有 Win32 程序"尚未开箱即用------当前推荐的迁移方式是"用 SOUI5 重写迁移"(UI 声明式重述 + Win32 逻辑保留,§4.2);要让任意既有 Win32 程序直接 0 成本跨端,还需补齐 swinx 的三块"迁移面"(原生控件库 / 窗口菜单栏 / 资源对话框)。需要强调的是:这属于待补齐的工作量,而非架构上的不确定性------支撑该需求的能力(以兼容层重演 Win32 语义、完整 Win32 内核对象支持、并以 platform/ 与 gdi/ 两个正交维度扩展平台与渲染)已经具备,缺的只是把这三块接口面逐一铺到 swinx 上;
  2. vendor 代码占比较高(换取零版本兼容风险),clone 与检索体验受影响;
  3. 项目维护集中度较高,持续演进依赖核心贡献者规模扩大。

六、数据溯源

关键数据的出处:

  • 源码规模 / 文件数: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:94``RuntimeLibrary="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.txt``APPLE 分支(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 资产可复用)恰是落地的前置条件。这笔权衡是否成立,取决于项目所处的具体语境,而非框架本身的绝对优劣。