- 桌面应用
- 跨平台
【免费下载链接】qt
Qt binding for Go (Golang) with support for Windows / macOS / Linux / FreeBSD / Android / iOS / Sailfish OS / Raspberry Pi / AsteroidOS / Ubuntu Touch / JavaScript / WebAssembly
本文以开源仓库 gh_mirrors/qt/qt 的官方 README 为骨架,系统讲解如何用 Go(以及 JavaScript/TypeScript、Dart/Flutter、Haxe、Swift)编写完整的 Qt 桌面与移动应用,覆盖 cgo 与无 cgo 两种安装路径、qtsetup与qtdeploy工具链的完整用法、面向 14+ 平台(Windows / macOS / Linux / Android / iOS / SailfishOS / WebAssembly 等)的部署矩阵,并从 qt.go、cmd/qtdeploy/main.go、internal/cmd/deploy/deploy.go 等源码出发,剖析信号连接、对象注册与跨语言绑定的底层实现。读完本文,你将掌握从零安装绑定、构建并打包一个 Qt 应用到目标平台的完整实战流程。
项目定位:用 Go 写 Qt 应用
Qt 本身是一个自由开源的跨平台图形用户界面(GUI)工具包,其核心价值在于:同一套底层代码可以在多种软件与硬件平台上运行而几乎不需要修改。而 Go(Golang)则是由 Google 设计的一门静态类型、编译型编程语言。
therecipe/qt绑定(本仓库即其镜像源码)做的事情是把两者结合起来:
- 允许直接用 Go 编写 Qt 应用,同时提供 JavaScript/TypeScript、Dart/Flutter、Haxe、Swift 等多语言入口;
- 大大简化了 Qt 应用向各类软件与硬件平台的部署流程——这正是 README 中最核心的定位;
- 覆盖面广:按 README 的表述,"almost all Qt functions and classes are accessible"(几乎所有 Qt 函数与类都可访问),足以支撑构建功能完整的 Qt 应用。
仓库顶层以 Qt 官方模块一一对应的方式组织,例如 core、gui、qml、quick、widgets、network、multimedia、sql、charts 等几十个 Go 包,可以直接按需导入。
仓库结构与工具链速览
在动手安装之前,先了解仓库的整体布局,有助于理解后文的命令:
- 顶层绑定包:
core/、gui/、widgets/、qml/、quick/等,每个目录对应一个 Qt 模块的 Go 绑定; - 命令行工具(位于 cmd/):
- qtdeploy:编译、打包并运行 Qt 应用;
- qtsetup:初始化、生成、安装绑定代码;
- qtmoc:运行 moc(Qt 元对象编译器);
- qtrcc:运行 rcc(Qt 资源编译器);
- qtminimal:生成最小化绑定;
- 内部实现(位于 internal/):
- internal/binding/parser:解析 Qt 头文件与文档,构建类/函数/枚举模型;
- internal/binding/templater:根据解析结果生成 Go/C++/cgo 代码模板;
- internal/cmd/deploy:部署流水线核心;
- internal/docker、internal/vagrant:跨平台部署所需的 Docker 镜像与 Vagrant 配置;
- internal/examples:大量可直接运行与学习的示例工程。
绑定层的核心运行时则集中在 qt.go,后面会专门剖析。
安装:前置条件与两种路径
README 给出的安装指令假设你已经安装好了Go与Git。在此基础上,提供两条路径:(实验性的)无 cgo 版本与默认版本。
(实验性)无 cgo 版本:最快体验方式
如果你刚接触这个绑定、只想快速测试一下,README 建议优先尝试无 cgo 的版本。它通过-ldflags="-w"去掉调试信息,并直接go get官方示例后运行:
Windows(PowerShell)
go get -ldflags="-w" github.com/therecipe/examples/basic/widgets && for /f %v in ('go env GOPATH') do %v\bin\widgets.exemacOS / Linux
go get -ldflags="-w" github.com/therecipe/examples/basic/widgets && $(go env GOPATH)/bin/widgets这条命令会拉取示例工程、编译并直接运行一个基于 Qt Widgets 的窗口程序,是最快的上手验证方式。
默认版本:完整安装
默认版本需要先安装 Qt 本身并准备好对应平台的工具链,然后通过qtsetup完成初始化和自测。README 按平台给出了官方命令(其中qtsetup test会构建并运行示例验证环境,qtsetup -test=false跳过示例测试只做完整安装):
Windows
set GO111MODULE=off go get -v github.com/therecipe/qt/cmd/... && for /f %v in ('go env GOPATH') do %v\bin\qtsetup test && %v\bin\qtsetup -test=falsemacOS
export GO111MODULE=off; xcode-select --install; go get -v github.com/therecipe/qt/cmd/... && $(go env GOPATH)/bin/qtsetup test && $(go env GOPATH)/bin/qtsetup -test=falseLinux
export GO111MODULE=off; go get -v github.com/therecipe/qt/cmd/... && $(go env GOPATH)/bin/qtsetup test && $(go env GOPATH)/bin/qtsetup -test=false三个平台的关键共同点:
GO111MODULE=off:需要关闭 Go Modules 模式,让代码通过 GOPATH 方式组织(仓库根目录 go.mod 声明了模块github.com/therecipe/qt,但在安装阶段 README 明确要求关闭 modules);go get -v github.com/therecipe/qt/cmd/...:一次性拉取并安装 cmd 下的全部子命令(qtsetup、qtdeploy、qtmoc、qtrcc、qtminimal);qtsetup test与qtsetup -test=false:先做自测,再正式安装(-test默认值为 true,见 cmd/qtsetup/main.go)。
macOS 额外需要执行xcode-select --install安装命令行开发者工具。
qtsetup:安装与代码生成的幕后机制
qtsetup是整个安装流程的引擎。从 cmd/qtsetup/main.go 的用法说明可以看到它支持多种模式(Modes):
| 模式 | 作用 |
|---|---|
prep | 把工具链软链接到 PATH 中 |
check | 执行一些基础环境检查 |
generate | 为所有包生成绑定代码 |
install | go install所有包 |
test | 构建并测试一些示例 |
full | 依次执行以上全部步骤(默认模式) |
update | 更新cmd与internal/cmd |
upgrade | 更新所有内容 |
其通用命令行格式为:
qtsetup [-debug] [mode] [target]常用 flag 包括:
-docker:在 Docker 容器内执行命令;-vagrant:在 Vagrant 虚拟机内执行;-dynamic:在生成与安装过程中创建并使用半动态库(实验性,非真正动态链接的替代品,且仅在非 Windows 平台可用);-failfast:安装步骤遇到第一个错误就退出;-test:安装结束后构建并运行示例应用(默认 true,即qtsetup -test=false关闭它)。
其中full模式是完整流程:prep→check→generate→install→test,可见 cmd/qtsetup/main.go。
generate模式背后是 internal/cmd/setup/generate.go:它调用parser.LoadModules(target)加载目标平台的 Qt 模块文档,然后逐模块调用templater.GenModule或templater.CgoTemplate生成 Go 绑定代码。生成代码所需的 Qt API 文档快照位于 internal/binding/files/docs,仓库内置了从 5.6.3 到 5.13.0 的多个版本索引;这也是qtsetup支持通过-qt_api指定 API 版本、通过-qt_version指定 Qt 版本的原因(见 internal/cmd/cmd.go)。
部署目标矩阵:一个命令,多平台交付
README 用一张表格列出了完整的部署目标支持情况,这是本绑定最突出的能力之一。原表如下(Linkage 一列的 dynamic/static/system 分别表示动态链接、静态链接、系统 Qt 链接):
| 目标平台 | 架构 | 链接方式 | Docker 部署 | 宿主系统 |
|---|---|---|---|---|
| Windows | 32 / 64 | dynamic / static | 是 | 任意 |
| macOS | 64 | dynamic | 是 | 任意 |
| Linux | arm / arm64 / 64 | dynamic / static / system | 是 | 任意 |
| Android(含 Wear) | arm / arm64 | dynamic | 是 | 任意 |
| Android-Emulator(含 Wear) | 32 | dynamic | 是 | 任意 |
| SailfishOS | arm | system | 是 | 任意 |
| SailfishOS-Emulator | 32 | system | 是 | 任意 |
| Raspberry Pi(1/2/3) | arm | dynamic / system | 是 | 任意 |
| Ubuntu Touch | arm / 64 | system | 是 | 任意 |
| JavaScript | 32 | static | 是 | 任意 |
| WebAssembly | 32 | static | 是 | 任意 |
| iOS | arm64 | static | 否 | macOS |
| iOS-Simulator | 64 | static | 否 | macOS |
| AsteroidOS | arm | system | 否 | Linux |
| FreeBSD | 32 / 64 | system | 否 | FreeBSD |
从这张表可以读出几个关键事实:
- 大多数目标都可以在任意宿主系统上通过 Docker 部署,这是"简化部署"承诺的具体体现;
- iOS 系列必须运行在 macOS 宿主上(受 Apple 工具链限制),AsteroidOS 与 FreeBSD 则分别限定 Linux 与 FreeBSD 宿主;
- JavaScript 与 WebAssembly 使用静态链接,输出可在浏览器中运行的应用。
部署在源码层如何实现
每个目标的交叉编译环境在 internal/cmd/cmd.go 的BuildEnv函数中集中定义:例如 Android 目标会设置GOOS=android、GOARCH=arm/arm64、CGO_ENABLED=1,并指定 NDK 中的 clang 作为CC/CXX;iOS 会通过-isysroot指向 Xcode 的 iPhoneOS SDK;Raspberry Pi 则使用rpi-tools的 arm-linux-gnueabihf 交叉编译器并区分GOARM(rpi1 为 6,rpi2/3 为 7)。
运行环节则由 internal/cmd/deploy/run.go 按目标分发:
- Android:通过
adb install -r build-debug.apk(或 release 签名包)安装到设备; - iOS-Simulator:通过
xcrun instruments -w启动模拟器,再simctl install/launch; - macOS:
open xxx.app; - Linux/FreeBSD:直接执行打包目录中的二进制;
- Windows(跨平台):通过
wine运行.exe; - SailfishOS-Emulator:借助
vboxmanage管理 VirtualBox 虚拟机并通过 SSH 安装 RPM 包; - js/wasm:在 macOS 上直接用 Firefox 打开生成的
index.html。
Docker / Vagrant 部署
qtdeploy、qtsetup、qtmoc、qtrcc均支持-docker与-vagrant参数,其实现集中在 internal/cmd/cmd.go:Docker 场景下会根据目标平台选择对应的镜像(例如 Windows 的windows_64_shared/windows_64_static、Android 的android、Sailfish 的sailfish),把 GOPATH 与项目目录挂载进容器后执行工具链命令;镜像定义在 internal/docker(含 Linux、Windows、macOS、Android、Sailfish、Raspberry Pi、Ubuntu Touch 等数十个 Dockerfile),Vagrant 配置则在 internal/vagrant。
qtdeploy:编译、打包、运行一站式命令
qtdeploy是日常开发使用频率最高的命令。从 cmd/qtdeploy/main.go 可知其用法为:
qtdeploy [-docker] [mode] [target] [path/to/project]模式(Modes)
| 模式 | 作用 |
|---|---|
build | 编译并打包 |
run | 运行二进制 |
test | 构建并运行 |
help | 打印帮助 |
常用 flags
| Flag | 作用 |
|---|---|
-docker | 在 Docker 容器内执行 |
-vagrant | 在 Vagrant 虚拟机内执行 |
-ldflags | 传递给每次go tool link调用的参数 |
-fast | 使用缓存的 moc、minimal 与依赖(适用于 windows、darwin、linux) |
-tags | 构建时视为已满足的 build tags 列表 |
-device | 指定 iOS 模拟器使用的设备 UUID |
-comply | 导出目标代码(object code),便于满足 LGPL 合规要求 |
-quickcompiler | 使用 quickcompiler |
-uic | 是否使用 uic(Qt 界面编译器),默认开启 |
target 可以传desktop(等价于当前宿主系统)、windows、darwin、linux、android、ios、sailfish、js、wasm等。项目路径可以省略(默认当前目录),也可以是尚未下载的包路径——此时qtdeploy会自动go get -d -v拉取(见 cmd/qtdeploy/main.go)。
部署流水线:rcc → moc → minimal → build → bundle
qtdeploy build/test的完整流程定义在 internal/cmd/deploy/deploy.go 的Deploy函数中,核心步骤为:
- 清空/重建
deploy/<target>输出目录(fast模式下对 js/wasm 会保留缓存); rcc.Rcc:扫描项目中的.qrc资源文件,用 Qt 的 rcc 工具生成资源绑定(由 internal/cmd/rcc/rcc.go 实现,qtrcc命令可单独调用);moc.Moc:对包含 Q_OBJECT 元信息的代码运行 Qt moc,生成元对象与信号槽支持代码(由 internal/cmd/moc/moc.go 实现,qtmoc命令可单独调用);minimal.Minimal:生成只包含项目实际用到的类的最小化绑定,显著减小体积与编译时间(对应 cmd/qtminimal);build:用BuildEnv设置好的交叉编译环境调用 go build;bundle:把 Qt 库、插件、QML 资源等按平台打包成可分发的产物(如 macOS 的.app、Windows 的 exe 目录、Android 的 APK);run:若模式为run/test,按上一节所述方式在目标平台启动应用。
注意-fast模式会跳过 moc/minimal 等重活以加快迭代(internal/cmd/deploy/deploy.go),适合桌面平台的开发调试。
编写第一个 Go + Qt 应用
仓库在 internal/examples 提供了大量示例,覆盖 Widgets、QML、OpenGL、Charts、WebEngine、Android 通知、蓝牙传输等场景。其中:
- Widgets 入门:internal/examples/common/widgets_demo(按钮、布局、表格等全套控件演示);
- QML 入门:internal/examples/qml/application、internal/examples/quick/calc;
- 经典 Widgets 示例:internal/examples/widgets/line_edits、internal/examples/widgets/table;
- 综合展示:internal/examples/showcases/wallet(包含 53 个 Go 文件的大型示例)。
典型开发流程(以 Widgets 为例):
# 1. 本地构建并运行 qtdeploy build desktop path/to/your/project qtdeploy run desktop path/to/your/project # 2. 交叉部署到目标平台(示例:Android) qtdeploy build android path/to/your/project # 3. 借助 Docker 在任何宿主上为 Windows 构建 qtdeploy -docker build windows path/to/your/project也可以直接用 Go 工具链开发调试:
go run ./main.goqtrcc与qtmoc支持单独调用(qtrcc [-docker] [target] [path/to/project]、qtmoc [-docker] [target] [path/to/project]),用于只做资源编译或元对象生成;qtmoc还提供-fast(不为依赖运行 moc)与-slow(降低资源占用)选项,见 cmd/qtmoc/main.go。
绑定运行时原理:信号、对象与 Go/C++ 互通
理解 qt.go 就能把握整个绑定的运行时机制。该文件维护了几张关键的全局表(均在 qt.go 声明),通过 mutex 保证并发安全:
- 信号表
signals/signalsJNI:以 C 指针(或 Android JNI 的字符串键)为键、信号名为二级键,映射到 Go 回调函数指针,支撑 Qt 信号到 Go 函数的连接; - 对象表
objects:记录 C 指针与对应 Go 对象(Register/Receive/Unregister三个函数配合使用),让 Go 侧能找回与 Qt 对象关联的 Go 包装实例; - 临时对象表
objectsTemp:存放跨语言传递的临时对象,防止被 GC 提前回收; - 连接类型表
connectionTypes:记录每个信号连接使用的连接模式(Qt::ConnectionType); - FuncMap / ItfMap / EnumMap:分别登记导出的 Go 函数、接口与枚举常量,供 Qt/C++ 侧反向调用,或供 QML/JS 运行时查找。
信号连接的核心 API 为:
ConnectSignal(cPtr, signal, function):把 Go 函数绑定到某个 Qt 对象(C 指针)的指定信号上;DisconnectSignal(cPtr, signal)/DisconnectAllSignals(cPtr, signal):解除绑定;GetSignal(cPtr, signal):取出已绑定的回调;当信号是destroyed或以~开头时,会自动在取出后清理全部连接(qt.go),防止对象销毁后悬空回调。
对象生命周期方面,SetFinalizer包装了 Go 的runtime.SetFinalizer,并在 qt.go 中做了去重与兜底处理:若同一 C 指针已注册过 finalizer,则新注册的 finalizer 会被替换为"将指针置空"的清理动作,避免重复释放。此外 qt.go 的init()中执行了runtime.LockOSThread()——这是 GUI 绑定的经典做法:把 Go 主线程锁定,保证 Qt 事件循环与 UI 操作始终在同一线程执行。
这些机制共同构成了 README 所说的"almost all Qt functions and classes are accessible"的运行时底座。
许可协议
本绑定以LGPLv3许可发布(LICENSE);Qt 本身采用多种许可方式提供,商用前请查阅 Qt 官方许可条款。对需要闭源/专有分发的场景,qtdeploy的-comply参数会导出目标代码,以便开发者更容易履行 LGPL 的合规义务。
总结
therecipe/qt绑定让 Go 开发者能够以纯 Go 代码构建功能完整的 Qt 应用,并通过qtsetup+qtdeploy工具链一键编译、打包、运行到 Windows / macOS / Linux / Android / iOS / SailfishOS / Raspberry Pi / Ubuntu Touch / JavaScript / WebAssembly 等十余种平台——多数目标还可借助 Docker 在任意宿主系统上完成部署。其底层由 qt.go 的信号表、对象注册表与函数/枚举映射表驱动,配合 internal/binding 的解析与模板生成体系,实现了 Qt C++ 与 Go 之间的双向互操作。新手可优先尝试无 cgo 版本快速跑通示例,随后按本文的默认安装路径完成完整环境搭建,即可开始用 Go 编写自己的跨平台桌面与移动应用。
- 桌面应用
- 跨平台
【免费下载链接】qt
Qt binding for Go (Golang) with support for Windows / macOS / Linux / FreeBSD / Android / iOS / Sailfish OS / Raspberry Pi / AsteroidOS / Ubuntu Touch / JavaScript / WebAssembly
相关推荐
GoQt:Golang 中的 Qt 跨平台应用框架绑定
GoQt:Golang 中的 Qt 跨平台应用框架绑定 项目基础介绍及编程语言 GoQt 是一个旨在将强大的 Qt 框架带入 Go 语言世界的开源项目。这个库利
UI库/组件桌面应用如何用Go语言Qt绑定快速构建跨平台GUI应用:终极完整指南
如何用Go语言Qt绑定快速构建跨平台GUI应用:终极完整指南 Go语言Qt绑定是一个强大的开源工具,让开发者能够使用Go语言轻松创建跨平台的桌面应用程序。这个绑
桌面应用跨平台ICU4X代码优化技巧:提升国际化功能执行效率的实用方法
ICU4X代码优化技巧:提升国际化功能执行效率的实用方法 ICU4X是一个为客户端和资源受限环境解决国际化问题的强大库。在开发过程中,优化代码以提升国际化功能的
后端
创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考