基于 MIT 许可的 Qt 绑定程序用于 Go
MIQT is MIT-licensed Qt bindings for Go.
This is a straightforward binding of the Qt 5.15 / Qt 6.4+ API using CGO. You must have a working Qt C++ development toolchain to use this Go binding.
These bindings were newly started in August 2024. The bindings are complete for QtCore, QtGui, QtWidgets, Qt SQL, QtMultimedia, QtMultimediaWidgets, QtSpatialAudio, QtPrintSupport, QtSvg, QtScript, QtNetwork, QtWebkit, QtWebChannel, QtWebEngine, QtCharts, QtPositioning, Qt Websockets, QStateMachine, QtUiPlugin/QtUiTools, QML, QScintilla, ScintillaEdit, Qwt, there is subclassing support, and there is a uic/rcc/lupdate implementation. But, the bindings may be immature in some ways. Please try out the bindings and raise issues if you have trouble.
| OS | Arch | Linkage | Status |
|---|---|---|---|
| Linux | x86_64 | Static or Dynamic (.so) | ✅ Works |
| Linux | ARM64 | Static or Dynamic (.so) | ✅ Works |
| Windows | x86_64 | Static or Dynamic (.dll) | ✅ Works |
| Android | ARM64 | Dynamic (bundled in .apk package) | ✅ Works |
| FreeBSD | x86_64 | Static or Dynamic (.so) | ✅ Works |
| macOS | x86_64 | Static or Dynamic (.dylib) | ✅ Works |
| macOS | ARM64 | Static or Dynamic (.dylib) | ✅ Works |
The MIQT Go bindings are licensed under the MIT license.
You must also meet your Qt license obligations.
These apps are listed in alphabetical order. Raise an issue or PR to have your app listed here!
MIQT is also used to produce Qt bindings to other programming languages:
Make sure to compile with go build -ldflags "-s -w". This reduces the helloworld example from 43MB to 6MB.
Then, it's possible to reduce the size further with upx --best to 2MB or upx --lzma to 1.4MB.
You can also try miqt-docker native -minify-build to use aggressive CFLAGS.
Yes. You must also meet your Qt license obligations: either use Qt dynamically-linked dll/so/dylib files under the LGPL, or, purchase a Qt commercial license for static linking.
The first time MIQT is used, your go build would take about 10 minutes. But after that, any go build is very fast.
Go 1.26 is significantly faster.
If you are compiling your app within a Dockerfile, you could cache the build step by running go install github.com/mappu/miqt/qt.
If you are compiling your app with a one-shot docker run command, the compile speed can be improved if you also bind-mount the Docker container's GOCACHE directory: -v $(pwd)/container-build-cache:/root/.cache/go-build. The miqt-docker helper app does this automatically.
See also issue #8.
MIQT is a clean-room binding that does not use any code from other Qt bindings.
Most functions are implemented 1:1. The Qt documentation should be used.
Container types:
QByteArray, QString, QList, QVector, QMap, QHash types are projected as plain Go []byte, string, []T, and map[K]V. Therefore, you can't call any of the Qt type's methods, you must use some Go equivalent method instead.QString::fromUtf8. Therefore, the Go string must be UTF-8 to avoid mojibake. If the Go string contains binary data, the conversion would corrupt such bytes into U+FFFD (�). On return to Go space, this becomes \xEF\xBF\xBD.QMap/QHash will differ from the Go map iteration order. QMap is iterated by key order, but Go maps and QHash iterate in an undefined internal order.Memory management:
QSize), the binding may have moved it to the heap, and in Go this may be represented as a pointer type. In such cases, a Go finalizer is added to automatically delete the heap object. This means code using MIQT can look basically similar to the Qt C++ equivalent code.Events and signals:
connect(sourceObject, sourceSignal, targetObject, targetSlot) is projected as targetObject.onSourceSignal(func()...).func() receives super() as a first argument that can be used to call the base class implementation.Class pointers:
var myLabel *qt.QLabel to a function taking only the *qt.QWidget base class, write myLabel.QWidget.QMenu::addAction(QString) vs QWidget::addAction(QAction*)), the base class version is shadowed and can only be called via myQMenu.QWidget.AddAction(QAction*).QTabWidget.CurrentWidget() == MyTab will never compare equal because CurrentWidget() created a new Go struct wrapping the same C++ pointer. You can compare QTabWidget.CurrentIndex(), or, you can use: QTabWidget.CurrentWidget().UnsafePointer() == MyTab.UnsafePointer().Multithreading:
qt.NewQApplication in MIQT, that will be considered the Qt main thread and will automatically signal the Go runtime to bind to a fixed OS thread using runtime.LockOSThread().(qt6/mainthread).Wait() or Start() to access the Qt objects from Qt's main thread.Android:
QFileDialog may return a filepath of the form content://.... Such paths can be opened with qt.QFile but not with Go os.Open(); you can pass the handle to Go using os.NewFile(QFile.Handle(), "name").Some C++ idioms that were difficult to project were omitted from the binding. But, this can be improved in the future.
MIQT has a custom implementation of Qt uic and rcc tools, to allow using Qt Designer for form design and resource management. After running the miqt-uic and miqt-rcc tools once, you can rebuild any changes using the convenient go generate command.
To install the tools, run:
go install github.com/mappu/miqt/cmd/miqt-uic@latest
go install github.com/mappu/miqt/cmd/miqt-rcc@latestThe tools are installed into your ~/go/bin directory. You could add this directory to your $PATH.
MIQT uses pkg-config to find all used Qt libraries. Every Qt library should have a definition file in .pc format, which provides CGO with the necessary CXXFLAGS/LDFLAGS. Your Qt development environment already included the necessary .pc definition files.
You can use the PKG_CONFIG_PATH environment variable to override where CGO looks for .pc files. Read more »
After changing the environment variable, you may need to run go clean -cache to ensure the next go build properly rebuilds MIQT against the changed Qt target. Otherwise, a previous Qt installation could be targeted from the cached build data.
The import path changes from github.com/mappu/miqt/qt to github.com/mappu/miqt/qt6, but most basic classes are the same.
You can update all imports by running find . -type f -name .go -exec sed -i 's_"github.com/mappu/miqt/qt"_qt "github.com/mappu/miqt/qt6"_' {} \;
Fork this repository and add your library to the genbindings/config-libraries file. Read more »
You can use the ordinary go get and go build commands. To help with cross-compilation, you can use the optional miqt-docker tool. Read more »
Tested with Debian 12 / Qt 5.15 + 6.4 / GCC 12
Tested with Fedora 40 + 41 / Qt 6.7 + 6.8 / GCC 14
For dynamic linking, with the system Qt (Qt 5):
# Debian / Ubuntu (Mini暂无开放 Issues,或尚未同步最近议题。