在这里插入图片描述

一、开源软件 QHexView 与 QHexViewNext 在鸿蒙上的差异

QHexView 是 virinext 开发的开源十六进制查看器,MIT 协议,约 849 行 C++ Qt 控件。它原本是纯 Linux/Windows 桌面工具,本次目标是将其移植到 HarmonyOS PC 平台。

与 MeldNext 的"UI 层 ArkTS 重写"路线不同,QHexViewNext 选择保留 Qt Widgets UI + libqohos 平台插件路线——Qt 源码几乎零修改即可运行。

维度原生 QHexView(Linux/Windows)QHexViewNext(鸿蒙 PC)
UI 框架Qt Widgets(QMainWindow/QMenuBar)Qt Widgets(完全保留
编程语言C++(Qt)C++(Qt)
运行形态桌面进程HAP(entry 模块)
UI 渲染QPA(窗口系统插件)libqohos(QPA for HarmonyOS)+ XComponent
差异引擎—(十六进制查看)—(十六进制查看,原样保留)
构建系统qmake / CMakeCMake + Hvigor
部署方式安装包HAP / APP(签名分发)
bundleNamecom.develop.opensource.qhexviewnext
设备支持x86/x86_64tablet、2in1(arm64)
商用分发源码开源AGC 上架

核心结论:QHexViewNext 100% 保留 Qt C++ 源码,仅通过 libqohos(Qt 平台插件)桥接鸿蒙 XComponent;改动集中在 CMake 工程化、字体/调色板适配与打包签名。


二、技术架构与技术原理

2.1 总体架构

┌─────────────────────────────────────────────────────────────┐
│                    ArkTS 壳 (UI 入口)                         │
│   QAbilityStage.ets / QAbility.ets / OhosExportModules.ts     │
│  创建 XComponent surface · 加载 native 模块 · NAPI 注册      │
└─────────────────────────────┬───────────────────────────────┘
                            调用 / 桥接
┌─────────────────────────────────────────────────────────────┐
│              libqohos.so (Qt 平台插件 QPA)                    │
│  桥接 Qt 窗口系统与鸿蒙 XComponent · 事件分发 · 调色板        │
└─────────────────────────────┬───────────────────────────────┘
                              调用
┌─────────────────────────────────────────────────────────────┐
│                       Qt 5.12.12 库                          │
│  Core / Gui / Widgets / DBus  +  libc++_shared.so 运行时      │
└─────────────────────────────┬───────────────────────────────┘
                              调用
┌─────────────────────────────────────────────────────────────┐
│                         应用本体                              │
│   libqhexview.so (132KB)                                    │
│   QHexView · MainWindow · 菜单栏 · 数据存储                  │
└─────────────────────────────────────────────────────────────┘

运行时 so 依赖:libqohos.so + libQt5{Core,Gui,Widgets,DBus}.so
             + libc++_shared.so + libqhexview.so(共 7 个)

2.2 核心技术原理

2.2.1 libqohos(Qt 平台插件 QPA)桥接机制

Qt 的跨平台能力依赖 QPA(Qt Platform Abstraction)——每个平台一个插件实现窗口/渲染/输入。libqohos.so 就是 Qt for HarmonyOS 的 QPA 插件:

  • 将 Qt 的窗口系统映射到鸿蒙 XComponent(surface 模式)
  • 将 Qt 事件循环接入鸿蒙事件分发
  • 提供 QClipboard / 调色板 / 光标等系统能力映射

QHexViewNext 不直接接触 N-API——Qt 源码调用 Qt API,libqohos 内部完成对鸿蒙 NAPI 的封装。这是与 MeldNext 最大的路线差异。

2.2.2 XComponent + Qt 渲染

libqohos 内部通过 XComponent(type=“surface”)获得原生渲染表面:

ArkTS 创建 XComponent → 传入 surfaceId
        ↓
libqohos: OH_NativeWindow_CreateNativeWindowFromSurfaceId(surfaceId)
        ↓
Qt 渲染引擎在 surface 上绘制(软件渲染,无需 OpenGL ES)
        ↓
eglSwapBuffers 上屏

QHexView 是纯 2D 控件(文本绘制为主),使用 Qt 软件渲染路径即可,不需要 OpenGL ES(MeldNext 的 Scintilla 编辑器才需要)。

2.2.3 QClipboard / 文件对话框适配
  • 剪贴板:Qt QApplication::clipboard() 由 libqohos 映射到鸿蒙 pasteboard,需要在 module.json5 申请 READ_PASTEBOARD 权限
  • 文件选择器QFileDialog::getOpenFileName 由 libqohos 映射到鸿蒙文件选择器,需要 FILE_ACCESS_PERSIST 权限持久化文件访问
2.2.4 调色板适配(防黑底)

libqohos 会把鸿蒙系统深色主题带进 Qt 调色板,导致 QMenuBar 黑底黑字不可读:

QPalette lightPalette;
lightPalette.setColor(QPalette::Window, QColor("#F0F0F0"));
lightPalette.setColor(QPalette::WindowText, Qt::black);
lightPalette.setColor(QPalette::Base, Qt::white);
lightPalette.setColor(QPalette::Text, Qt::black);
lightPalette.setColor(QPalette::Button, QColor("#F0F0F0"));
lightPalette.setColor(QPalette::ButtonText, Qt::black);
app.setPalette(lightPalette);   // 不要 setStyle,避免改变控件外观

三、底层依赖介绍及移植要求

3.1 移植库一览

QHexViewNext 依赖 Qt 5.12.12 for OHOS 最小子集(98MB):

库/组件版本在 QHexViewNext 中的角色移植方式复用率
Qt5Core5.12.12事件循环/字符串/QSettings预编译 so + 头文件100%
Qt5Gui5.12.12字体/绘制/剪贴板预编译 so + 头文件100%
Qt5Widgets5.12.12QMainWindow/QMenuBar/QHexView预编译 so + 头文件100%
Qt5DBus5.12.12libqohos 依赖(DT_NEEDED)预编译 so100%
libqohosQPA 平台插件Qt SDK 提供100%
libc++_sharedC++ 标准库运行时NDK 提供100%
QHexView 源码virinext应用本体原样保留~99%

QHexView 源码仅改动 2 处(字体 + 标题),复用率 ~99%,远高于 MeldNext 的 95%。

3.2 移植到 HarmonyOS 需要满足的要求

3.2.1 编译工具链
  • 编译器:Clang 15(OHOS NDK 自带,非 GCC)
  • 标准:CMake 3.5+,必须使用 ohos.toolchain.cmake 或 DevEco 的 hmos.toolchain.cmake
  • 架构:-DOHOS_ARCH=arm64-v8a(鸿蒙 PC 为 arm64)
3.2.2 CMake 关键写法
# 必做①:候选路径存在性校验(防 .cxx 缓存假命中)
set(_QT_PREFIX_CANDIDATES "")
if(DEFINED QT_PREFIX AND NOT QT_PREFIX STREQUAL "")
    list(APPEND _QT_PREFIX_CANDIDATES "${QT_PREFIX}")
endif()
list(APPEND _QT_PREFIX_CANDIDATES
    "${CMAKE_CURRENT_SOURCE_DIR}/third_party/qt-5.12.12-ohos-arm64"
    "C:/Qt/5.12.12-ohos-arm64")
set(QT_PREFIX "")
foreach(_cand IN LISTS _QT_PREFIX_CANDIDATES)
    if(EXISTS "${_cand}/lib/cmake/Qt5/Qt5Config.cmake")
        set(QT_PREFIX "${_cand}"); break()
    else()
        message(WARNING "QT_PREFIX 候选路径无效,已跳过: ${_cand}")
    endif()
endforeach()

# 必做②:交叉 toolchain 下显式钉死模块 config 目录
set(Qt5Core_DIR    "${QT_PREFIX}/lib/cmake/Qt5Core"    CACHE PATH "" FORCE)
set(Qt5Gui_DIR     "${QT_PREFIX}/lib/cmake/Qt5Gui"     CACHE PATH "" FORCE)
set(Qt5Widgets_DIR "${QT_PREFIX}/lib/cmake/Qt5Widgets" CACHE PATH "" FORCE)
set(CMAKE_AUTOMOC ON)
3.2.3 Qt 源码改造(字体)
QFont font("Noto Sans Mono", 10);
font.setStyleHint(QFont::Monospace);
setFont(font);

鸿蒙 PC 自带 Noto Sans Mono 字体,确保三栏(地址 / Hex / ASCII)严格等宽对齐。

3.2.4 运行时 .so 清单

entry/libs/arm64-v8a/ 必须包含 7 个 .so:

.so大小作用
libqhexview.so132KB应用本体(用户代码)
libqohos.so5.5MBQt 平台插件 QPA
libQt5Widgets.so6.4MBQt 控件
libQt5Core.so5.0MBQt 内核
libQt5Gui.so4.5MBQt GUI
libQt5DBus.so557KBlibqohos 依赖(DT_NEEDED)
libc++_shared.so1.3MBC++ 标准库(预编模式下必须手动放

四、移植流程

4.1 总体移植流程

                    QHexViewNext 鸿蒙化
                            │
        ┌───────────┬───────┴───────┬─────────────┐
        ▼           ▼               ▼             ▼
   QHexView.cpp  main.cpp     CMakeLists.txt   third_party/
   (Qt 控件)    (入口+调色板)   (OHOS toolchain) Qt 5.12.12 for OHOS
   ~849 行 C++                                          98MB 最小子集
        └───────────┴───────┬───────┴─────────────┘
                            ▼
            ┌──────────────────────────────┐
            │  交叉编译 (Clang 15 + AUTOMOC)  │
            │      → libqhexview.so        │
            └──────────────┬───────────────┘
                            ▼
            ┌──────────────────────────────┐
            │    hvigor 打包 + 签名         │
            │  → entry-default-signed.hap  │
            │    (24MB, 7 个 .so)          │
            └──────────────┬───────────────┘
                            ▼
            ┌──────────────────────────────┐
            │   华为鸿蒙 PC (2in1 · arm64)  │
            │    hdc install / Run         │
            └──────────────────────────────┘

保留 Qt C++ 源码 · 不改写 ArkUI · libqohos 平台插件桥接

5 个阶段:环境准备 → Qt 子集提取 → CMake 编译 → 集成 DevEco → 签名 + 安装。

4.2 编译指令

4.2.1 CMake 编译(自动由 Hvigor 调用)

entry/build-profile.json5

"buildOption": {
  "externalNativeOptions": {
    "path": "./src/main/cpp/CMakeLists.txt",
    "arguments": "",
    "cppFlags": "",
    "abiFilters": ["arm64-v8a"]
  }
}

手动调试命令(模拟 Hvigor):

SDK="<DevEco>/sdk/default/openharmony/native"
"$SDK/build-tools/cmake/bin/cmake.exe" -B <tmp> -G Ninja \
  -DCMAKE_TOOLCHAIN_FILE="$SDK/build/cmake/ohos.toolchain.cmake" \
  -DOHOS_STL=c++_shared -DOHOS_ARCH=arm64-v8a -DOHOS_PLATFORM=OHOS \
  -DCMAKE_MAKE_PROGRAM="$SDK/build-tools/cmake/bin/ninja.exe"
"$SDK/build-tools/cmake/bin/cmake.exe" --build <tmp> --parallel
4.2.2 Qt 最小子集提取

从 Qt 5.12.12 for OHOS 提取:

  • include/lib/cmake/lib/libQt5{Core,Gui,Widgets,DBus}.somkspecs/(全量)
  • bin/ 主机工具:不能只拷 moc.exe——Qt5 的 ConfigExtras.cmake 启动时对 qmake/moc/rcc/uic 做存在性检查,用 grep -rh -oE 'bin/[A-Za-z0-9_]+\.exe' lib/cmake/ | sort -u 列出全部引用
  • plugins/:按 Qt5*Plugin.cmake 中的 RELEASE 路径逐个拷贝插件 .so
  • 清除烙死路径:自编译 Qt 会把构建机 sysroot 烙进 Qt5GuiConfigExtras.cmake,需改为动态定位
4.2.3 转测分发(预编 .so 模式)
┌──────────────┐   robocopy       ┌──────────────┐   hvigor    ┌──────────────┐
│   开发机      │ ──── 暂存 ────→ │   转测包      │ ────→      │   测试机      │
│              │     转换        │  (精简 ~16MB) │             │              │
│ 完整工程      │                 │              │             │ 零 Qt 依赖  │
│ + third_party │                 │  7 个预编 .so │             │ + 自动签名  │
│ + 编 C++      │                 │  → entry/libs │             │              │
└──────────────┘                 └──────────────┘             └──────────────┘

robocopy <dev> <stage> /E /XD .cxx build .hvigor oh_modules .idea signing /XF *.iml *.p12 *.p7b *.cer

4.3 上下层交互方式

4.3.1 ArkTS ↔ libqohos 桥接

QHexViewNext 的 ArkTS 壳(QtSDK 官方模板,原样使用):

// QAbilityStage.ets —— 生命周期入口
// QAbility.ets —— 创建 XComponent,把 surfaceId 传给 native
// OhosExportModules.ts —— NAPI 模块注册表(删掉 lazy import 关键字)

Qt 源码完全不知道鸿蒙存在——所有鸿蒙交互都由 libqohos 承接

4.3.2 系统能力映射
Qt API鸿蒙系统能力需要的权限
QApplication::clipboard()pasteboardREAD_PASTEBOARD
QFileDialog文件选择器FILE_ACCESS_PERSIST
QSettings数据持久化STORE_PERSISTENT_DATA
QProcess进程管理PREPARE_APP_TERMINATE

4.4 关键配置文件

配置文件作用
AppScope/app.json5bundleName / 版本 / 图标(app_name)
build-profile.json5(根)signingConfigs + products(signingConfig 引用不能删)
build-profile.json5(entry)externalNativeOptions(CMake 配置)
module.json5模块配置 + 权限声明(精简到 5 个)
oh-package.json5依赖声明(libentry.so / libqohos.so)
signing/*签名材料(release.p12/cer/p7b,不入 git

4.5 注意事项

  1. moc.exe 是 MinGW 编译的(不是 MSVC)——诊断 0xc0000135 时要查 llvm-readobj --coff-imports 导入表,PATH 加 C:\Program Files\Git\mingw64\bin
  2. libc++_shared.so 预编模式下必须手动放入 entry/libs,否则 libqohos 加载失败闪退
  3. signingConfig 引用不能删:转测包清签名只清 signingConfigs: [],保留 product 的 "signingConfig": "default"
  4. 权限最小化:17 个删到 5 个(SYSTEM_FLOAT_WINDOW 等一律删,AGC 受限权限审核严)
  5. 签名算法 SHA256withECDSA,Profile 用发布版(qhexviewnextRelease.p7b
  6. 工程路径不含空格和中文(Qt 工具链兼容性)
  7. 混淆永不启用(libqohos 按名字回调 ArkTS,混淆断桥接闪退)

五、移植总结

5.1 移植模式

模式适用工作量QHexViewNext 采用
源码内嵌 + N-API小型库(diffutils/uchardet)★☆☆
源码适配 + XComponent需原生渲染的组件(Scintilla)★★★
保留 Qt + QPA 平台插件Qt 系应用★★☆✅ 是
Lycium/HNP 独立二进制命令行工具(Git/SVN)★☆☆

5.2 关键技术决策

  1. 保留 Qt Widgets UI,不改写 ArkUI——改造成本几乎为零
  2. C++ 源码 ~99% 复用,仅改字体/标题 2 处
  3. libqohos 平台插件承接全部鸿蒙桥接(QPA 机制)
  4. third_party 内置 Qt 子集,工程可移植、测试机免安装
  5. 预编 .so 转测分发,测试机零 C++ 编译

5.3 效果

  • 代码复用率:Qt 源码 ~99% 未修改
  • 功能完整性:十六进制查看、打开文件、复制粘贴、跳转、菜单均正常
  • 体积:HAP 24MB(其中 Qt 框架库 23MB,应用本体仅 132KB/0.5%)
HAP 24MB 体积构成(应用本体仅 0.5%):

  libQt5Widgets.so    6.4M  ████████████████  27%
  libqohos.so          5.5M  ██████████████    23%
  libQt5Core.so        5.0M  ████████████      21%
  libQt5Gui.so         4.5M  ███████████       19%
  libc++_shared.so     1.3M  ███                5%
  libQt5DBus.so        0.6M  █                  2%
  libqhexview.so       0.1M  ▏                 0.5%   ← 应用本体
  其他(资源 + ArkTS)  0.6M  ▏                  2%

5.4 真实运行效果

鸿蒙 PC 真机(1920×1280)打开本地文件:

在这里插入图片描述

三栏等宽布局(地址 / Hex / ASCII)严格按列对齐,菜单栏 / 弹窗 / 选中态正常,UI 与原版 Qt 程序一致。

Logo

赋能鸿蒙PC开发者,共建全场景原生生态,共享一次开发多端部署创新价值。

更多推荐