桌面端跨平台¶
Warning
The current page still doesn't have a translation for this language.
You can read it through google translate.
SOUI 的桌面端覆盖 Windows / Linux / macOS。三者的共同点是:应用进程拥有自己的入口和事件循环,因此不需要任何外部桥接库——Windows 直接用系统 Win32;Linux 与 macOS 由 swinx 在模块内部实现全部平台 API。
平台分层与 swinx 的定位见 跨平台开发概述。
三平台对比¶
| 维度 | Windows | Linux | macOS |
|---|---|---|---|
| 是否编译 swinx | 否(用系统 Win32) | 是 | 是 |
| swinx 平台层 | — | swinx/src/platform/linux |
swinx/src/platform/cocoa |
| 构建片段 | 根 CMakeLists.txt Windows 分支 |
swinx/linux.cmake |
swinx/macos.cmake |
| 窗口系统 | 原生 Win32 窗口 | X11(通过 xcb) | Cocoa / AppKit(SNsWindow) |
| swinx 2D 后端 | 系统 GDI(无翻译层) | Cairo(src/gdi/cairo) |
Core Graphics(src/gdi/apple) |
| 事件泵 | 系统消息队列 | poll() + xcb_poll_for_event() |
SwinXApplication(NSApplication 子类) |
WCHAR_SIZE |
2 | 4 | 4 |
| 托盘图标 | 原生 Shell_NotifyIcon | _NET_SYSTEM_TRAY(STrayIconMgr) |
STrayIconMgr(AppKit) |
| 输入法 | 原生 IMM32 | xcb-imdkit(XIM) | SImContext(AppKit 文本输入) |
统一的入口模型¶
桌面端三平台共用同一个 Win32 风格入口 _tWinMain;非 Windows 平台只需一个薄 main() 转发。以 games/cnchess/client/main.cc 为例:
int WINAPI _tWinMain(HINSTANCE hInstance, HINSTANCE, LPTSTR lpstrCmdLine, int)
{
SApplication app(hInstance);
// 注册皮肤 / 窗口类
app.RegisterSkinClass<SSkinAni>();
app.RegisterWindowClass<CChessBoard>();
SAppCfg cfg;
cfg.SetRender(Render_Skia) // 选择 SOUI 渲染工厂
.SetImgDecoder(ImgDecoder_Stb)
.SetLog(TRUE);
#ifdef _WIN32
cfg.SetSysResPeFile(appDir + _T("/soui-sys-resource.dll")); // 资源来自 PE 文件
cfg.SetAppResPeHandle(hInstance);
#else
cfg.SetSysResZip(strSysRes, ""); // 或 SetSysResFile(目录)
cfg.SetAppResZip(strAppRes, ""); // 或 SetAppResFile(目录)
#endif
cfg.DoConfig(&app);
#ifndef _WIN32
AddFontResource(strFont.c_str()); // 非 Windows 需显式加载字体
#endif
CMainDlg dlgMain(theme);
dlgMain.Create(GetActiveWindow());
dlgMain.SendMessage(WM_INITDIALOG);
dlgMain.ShowWindow(SW_SHOWNORMAL);
return app.Run(dlgMain.m_hWnd);
}
// Linux / macOS 的薄入口(Windows 由 CRT 直接调用 _tWinMain)
#if !defined(_WIN32) || defined(__MINGW32__)
int main(int argc, char **argv)
{
HINSTANCE hInst = GetModuleHandle(NULL);
return _tWinMain(hInst, 0, NULL, SW_SHOWNORMAL);
}
#endif
注意 Linux 与 macOS 都是直接转发:swinx 的窗口系统连接(xcb / NSApplication)在 SConnection 首次使用时惰性建立,不需要应用显式初始化。
资源加载的平台差异¶
SAppCfg 为不同平台提供了不同的资源来源接口,这是桌面端唯一必须区分平台的地方:
| 平台 | 系统资源(soui-sys-resource) | 应用资源(uires) |
|---|---|---|
| Windows | SetSysResPeFile("soui-sys-resource.dll") |
SetAppResPeHandle(hInstance) |
| Linux | SetSysResZip(...) 或 SetSysResFile(目录) |
SetAppResZip(...) 或 SetAppResFile(目录) |
| macOS | 同 Linux,路径指向 .app Bundle 内的 Resources |
同 Linux |
字体方面:Windows 通常直接使用系统字体;Linux 与 macOS 建议在 DoConfig 之后用 AddFontResource() 显式加载随包分发的字体文件(如 simsun.ttc),避免不同发行版字体缺失导致的排版差异。
跨平台编码建议¶
-
用预定义宏隔离平台差异,不要在业务代码里直接调用平台原生 API:
#ifdef _WIN32 // Windows 专属 #elif defined(__APPLE__) // macOS / iOS 共用 #ifdef __IOS__ // 仅 iOS #endif #elif defined(__ANDROID__) // Android #elif defined(__OHOS__) // 鸿蒙 #else // Linux #endif其中
__IOS__与__OHOS__是 SOUI 构建体系添加的宏(分别在根CMakeLists.txt与swinx/mobile.cmake中定义),不是编译器内置宏。 -
差异收敛到入口处:让
SAppCfg(资源来源、渲染工厂、日志)承担所有平台判断,业务窗体、控件、布局、消息处理保持平台无关。 - 不要假设
wchar_t是 2 字节:跨平台代码统一用SStringT/_T(),需要固定宽度时用SStringA/SStringW并注意WCHAR_SIZE。 - 路径分隔符与大小写:Linux 文件系统区分大小写,资源文件名与 XML 中的引用必须完全一致。