mirror of
https://github.com/mappu/miqt.git
synced 2024-12-22 00:48:38 +00:00
qt6: initial support
This commit is contained in:
parent
aed94883cf
commit
ab84c70f03
@ -10,7 +10,7 @@
|
||||
|
||||
MIQT is MIT-licensed Qt bindings for Go.
|
||||
|
||||
This is a straightforward binding of the Qt API using CGO. You must have a working Qt C++ development toolchain to use this Go binding.
|
||||
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 functional for all of QtCore, QtGui, and QtWidgets, and there is a uic/rcc implementation. But, the bindings may be immature in some ways. Please try out the bindings and raise issues if you have trouble.
|
||||
|
||||
|
@ -5,25 +5,56 @@ import (
|
||||
"strings"
|
||||
)
|
||||
|
||||
func InsertTypedefs() {
|
||||
func InsertTypedefs(qt6 bool) {
|
||||
|
||||
// Seed well-known typedefs
|
||||
pp := "qt"
|
||||
if qt6 {
|
||||
pp = "qt6"
|
||||
}
|
||||
|
||||
// QString is deleted from this binding
|
||||
KnownTypedefs["QStringList"] = lookupResultTypedef{"qt", CppTypedef{"QStringList", parseSingleTypeString("QList<QString>")}}
|
||||
KnownTypedefs["QStringList"] = lookupResultTypedef{pp, CppTypedef{"QStringList", parseSingleTypeString("QList<QString>")}}
|
||||
|
||||
// FIXME this isn't picked up automatically because QFile inherits QFileDevice and the name refers to its parent class
|
||||
KnownTypedefs["QFile::FileTime"] = lookupResultTypedef{"qt", CppTypedef{"QFile::FileTime", parseSingleTypeString("QFileDevice::FileTime")}}
|
||||
KnownTypedefs["QFile::FileTime"] = lookupResultTypedef{pp, CppTypedef{"QFile::FileTime", parseSingleTypeString("QFileDevice::FileTime")}}
|
||||
|
||||
if !qt6 {
|
||||
// n.b. Qt 5 only
|
||||
KnownTypedefs["QLineF::IntersectionType"] = lookupResultTypedef{"qt", CppTypedef{"QLineF::IntersectionType", parseSingleTypeString("QLineF::IntersectType")}}
|
||||
KnownTypedefs["QLineF::IntersectionType"] = lookupResultTypedef{pp, CppTypedef{"QLineF::IntersectionType", parseSingleTypeString("QLineF::IntersectType")}}
|
||||
} else {
|
||||
// Must be removed for Qt 6
|
||||
}
|
||||
|
||||
// Not sure the reason for this one
|
||||
KnownTypedefs["QSocketDescriptor::DescriptorType"] = lookupResultTypedef{"qt", CppTypedef{"QSocketDescriptor::DescriptorType", parseSingleTypeString("QSocketNotifier::Type")}}
|
||||
KnownTypedefs["QSocketDescriptor::DescriptorType"] = lookupResultTypedef{pp, CppTypedef{"QSocketDescriptor::DescriptorType", parseSingleTypeString("QSocketNotifier::Type")}}
|
||||
|
||||
// QFile doesn't see QFileDevice parent class enum
|
||||
KnownTypedefs["QFile::Permissions"] = lookupResultTypedef{"qt", CppTypedef{"QFile::Permissions", parseSingleTypeString("QFileDevice::Permissions")}}
|
||||
KnownTypedefs["QFileDevice::Permissions"] = lookupResultTypedef{"qt", CppTypedef{"QFile::Permissions", parseSingleTypeString("QFlags<QFileDevice::Permission>")}}
|
||||
KnownTypedefs["QFile::Permissions"] = lookupResultTypedef{pp, CppTypedef{"QFile::Permissions", parseSingleTypeString("QFileDevice::Permissions")}}
|
||||
KnownTypedefs["QFileDevice::Permissions"] = lookupResultTypedef{pp, CppTypedef{"QFile::Permissions", parseSingleTypeString("QFlags<QFileDevice::Permission>")}}
|
||||
KnownTypedefs["QIODevice::OpenMode"] = lookupResultTypedef{pp, CppTypedef{"QIODevice::OpenMode", parseSingleTypeString("QIODeviceBase::OpenMode")}}
|
||||
|
||||
if qt6 {
|
||||
// Qt 6 QVariant helper types - needs investigation
|
||||
KnownTypedefs["QVariantHash"] = lookupResultTypedef{"qt6", CppTypedef{"QVariantHash", parseSingleTypeString("QHash<QString,QVariant>")}}
|
||||
KnownTypedefs["QVariantList"] = lookupResultTypedef{"qt6", CppTypedef{"QVariantList", parseSingleTypeString("QList<QVariant>")}}
|
||||
KnownTypedefs["QVariantMap"] = lookupResultTypedef{"qt6", CppTypedef{"QVariantMap", parseSingleTypeString("QMap<QString,QVariant>")}}
|
||||
|
||||
// Qt 6 renamed the enum to LibraryPath, but left some uses of LibraryLocation with a typedef
|
||||
// We don't find the typedef - needs investigation
|
||||
// ONLY add this on Qt 6 builds, breaks Qt 5
|
||||
KnownTypedefs["QLibraryInfo::LibraryLocation"] = lookupResultTypedef{"qt6", CppTypedef{"QLibraryInfo::LibraryLocation", parseSingleTypeString("QLibraryInfo::LibraryPath")}}
|
||||
|
||||
// Enums
|
||||
|
||||
// QSysInfo.h is being truncated and not finding any content
|
||||
KnownEnums["QSysInfo::Endian"] = lookupResultEnum{"qt6", CppEnum{
|
||||
EnumName: "QSysInfo::Endian",
|
||||
UnderlyingType: CppParameter{
|
||||
ParameterType: "int",
|
||||
},
|
||||
}}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@ -50,7 +81,13 @@ func AllowHeader(fullpath string) bool {
|
||||
"qstring.h", // QString does not exist in this binding
|
||||
"qbytearray.h", // QByteArray does not exist in this binding
|
||||
"qlist.h", // QList does not exist in this binding
|
||||
"qvector.h": // QVector does not exist in this binding
|
||||
"qvector.h", // QVector does not exist in this binding
|
||||
"qtcoreexports.h", // Nothing bindable here and has Q_CORE_EXPORT definition issues
|
||||
"q20algorithm.h", // Qt 6 unstable header
|
||||
"q20functional.h", // Qt 6 unstable header
|
||||
"q20iterator.h", // Qt 6 unstable header
|
||||
"q23functional.h", // Qt 6 unstable header
|
||||
"____last____":
|
||||
return false
|
||||
}
|
||||
|
||||
@ -79,7 +116,9 @@ func ImportHeaderForClass(className string) bool {
|
||||
case "QGraphicsEffectSource", // e.g. qgraphicseffect.h
|
||||
"QAbstractConcatenable", // qstringbuilder.h
|
||||
"QTextEngine", // qtextlayout.h
|
||||
"QText": // e.g. qtextcursor.h
|
||||
"QText", // e.g. qtextcursor.h
|
||||
"QVLABaseBase", // e.g. Qt 6 qvarlengtharray.h
|
||||
"____last____":
|
||||
return false
|
||||
}
|
||||
|
||||
@ -107,7 +146,17 @@ func AllowClass(className string) bool {
|
||||
"QUnhandledException", // As above (child class)
|
||||
"QItemSelection", // Extends a QList<>, too hard
|
||||
"QXmlStreamAttributes", // Extends a QList<>, too hard
|
||||
"QPolygon", "QPolygonF": // Extends a QVector<QPoint> template class, too hard
|
||||
"QPolygon", // Extends a QVector<QPoint> template class, too hard
|
||||
"QPolygonF", // Extends a QVector<QPoint> template class, too hard
|
||||
"QAssociativeIterator", // Qt 6. Extends a QIterator<>, too hard
|
||||
"QAssociativeConstIterator", // Qt 6. Extends a QIterator<>, too hard
|
||||
"QAssociativeIterable", // Qt 6. Extends a QIterator<>, too hard
|
||||
"QSequentialIterator", // Qt 6. Extends a QIterator<>, too hard
|
||||
"QSequentialConstIterator", // Qt 6. Extends a QIterator<>, too hard
|
||||
"QSequentialIterable", // Qt 6. Extends a QIterator<>, too hard
|
||||
"QBrushDataPointerDeleter", // Qt 6 qbrush.h. Appears in header but cannot be linked
|
||||
"QPropertyBindingPrivatePtr", // Qt 6 qpropertyprivate.h. Appears in header but cannot be linked
|
||||
"____last____":
|
||||
return false
|
||||
}
|
||||
|
||||
@ -115,8 +164,15 @@ func AllowClass(className string) bool {
|
||||
}
|
||||
|
||||
func AllowSignal(mm CppMethod) bool {
|
||||
if mm.ReturnType.ParameterType != "void" {
|
||||
// This affects how we cast the signal function pointer for connect
|
||||
// It would be fixable, but, real signals always have void return types anyway
|
||||
return false
|
||||
}
|
||||
|
||||
switch mm.MethodName {
|
||||
case `metaObject`, `qt_metacast`:
|
||||
case `metaObject`, `qt_metacast`,
|
||||
`clone`: // Qt 6 - qcoreevent.h
|
||||
return false
|
||||
default:
|
||||
return true
|
||||
@ -194,6 +250,19 @@ func CheckComplexity(p CppParameter, isReturnType bool) error {
|
||||
if strings.HasPrefix(p.ParameterType, "FillResult<") {
|
||||
return ErrTooComplex // Scintilla
|
||||
}
|
||||
if strings.HasPrefix(p.ParameterType, "QBindable<") {
|
||||
return ErrTooComplex // e.g. Qt 6 qabstractanimation.h
|
||||
}
|
||||
if strings.HasPrefix(p.ParameterType, "QRgbaFloat<") {
|
||||
return ErrTooComplex // e.g. Qt 6 qcolortransform.h
|
||||
}
|
||||
if strings.HasPrefix(p.ParameterType, "QPointer<") {
|
||||
return ErrTooComplex // e.g. Qt 6 qevent.h . It should be possible to support this
|
||||
}
|
||||
if strings.HasPrefix(p.ParameterType, "EncodedData<") {
|
||||
return ErrTooComplex // e.g. Qt 6 qstringconverter.h
|
||||
}
|
||||
|
||||
if strings.HasPrefix(p.ParameterType, "std::") {
|
||||
// std::initializer e.g. qcborarray.h
|
||||
// std::string QByteArray->toStdString(). There are QString overloads already
|
||||
@ -212,12 +281,21 @@ func CheckComplexity(p CppParameter, isReturnType bool) error {
|
||||
if strings.Contains(p.GetQtCppType().ParameterType, `::DataPtr`) {
|
||||
return ErrTooComplex // e.g. QImage::data_ptr()
|
||||
}
|
||||
if strings.Contains(p.ParameterType, `::DataPointer`) {
|
||||
return ErrTooComplex // Qt 6 qbytearray.h. This could probably be made to work
|
||||
}
|
||||
if strings.HasPrefix(p.ParameterType, `QArrayDataPointer<`) {
|
||||
return ErrTooComplex // Qt 6 qbytearray.h. This could probably be made to work
|
||||
}
|
||||
|
||||
// Some QFoo constructors take a QFooPrivate
|
||||
// QIcon also returns a QIconPrivate
|
||||
if p.ParameterType[0] == 'Q' && strings.HasSuffix(p.ParameterType, "Private") {
|
||||
return ErrTooComplex
|
||||
}
|
||||
if strings.HasPrefix(p.ParameterType, "QtPrivate::") {
|
||||
return ErrTooComplex // e.g. Qt 6 qbindingstorage.h
|
||||
}
|
||||
|
||||
// If any parameters are QString*, skip the method
|
||||
// QDebug constructor
|
||||
@ -260,6 +338,8 @@ func CheckComplexity(p CppParameter, isReturnType bool) error {
|
||||
"QPolygon", "QPolygonF", // QPolygon extends a template type
|
||||
"QGenericMatrix", "QMatrix3x3", // extends a template type
|
||||
"QLatin1String", "QStringView", // e.g. QColor constructors and QColor::SetNamedColor() overloads. These are usually optional alternatives to QString
|
||||
"QLatin1StringView", // Qt 6 - used in qanystringview
|
||||
"QUtf8StringView", // Qt 6 - used in qdebug
|
||||
"QStringRef", // e.g. QLocale::toLongLong and similar overloads. As above
|
||||
"qfloat16", // e.g. QDataStream - there is no such half-float type in C or Go
|
||||
"char16_t", // e.g. QChar() constructor overload, just unnecessary
|
||||
@ -289,7 +369,12 @@ func CheckComplexity(p CppParameter, isReturnType bool) error {
|
||||
"QPlatformScreen", // e.g. qscreen.h. as below
|
||||
"QPlatformWindow", // e.g. qwindow.h, as below
|
||||
"QPlatformSurface", // e.g. qsurface.h. as below
|
||||
"QPlatformMenu": // e.g. QMenu_PlatformMenu. Defined in the QPA, could probably expose as uintptr
|
||||
"QPlatformMenu", // e.g. QMenu_PlatformMenu. Defined in the QPA, could probably expose as uintptr
|
||||
"struct _XDisplay", // Qt 6 QGuiApplication_platform
|
||||
"xcb_connection_t", // Qt 6 QGuiApplication_platform
|
||||
"QTextDocument::ResourceProvider", // Qt 6 typedef for unsupported std::function<QVariant(const QUrl&)>
|
||||
"QTransform::Affine", // Qt 6 qtransform.h - public method returning private type
|
||||
"____last____":
|
||||
return ErrTooComplex
|
||||
}
|
||||
|
||||
|
@ -25,7 +25,7 @@ var (
|
||||
KnownEnums map[string]lookupResultEnum
|
||||
)
|
||||
|
||||
func init() {
|
||||
func flushKnownTypes() {
|
||||
KnownClassnames = make(map[string]lookupResultClass)
|
||||
KnownTypedefs = make(map[string]lookupResultTypedef)
|
||||
KnownEnums = make(map[string]lookupResultEnum)
|
||||
|
@ -99,6 +99,9 @@ func main() {
|
||||
|
||||
flag.Parse()
|
||||
|
||||
flushKnownTypes()
|
||||
InsertTypedefs(false)
|
||||
|
||||
generate(
|
||||
"qt",
|
||||
[]string{
|
||||
@ -146,6 +149,25 @@ func main() {
|
||||
*outDir,
|
||||
(&clangMatchUnderPath{filepath.Join(*extraLibsDir, "scintilla")}).Match,
|
||||
)
|
||||
|
||||
// FLUSH all known typedefs / ...
|
||||
|
||||
flushKnownTypes()
|
||||
InsertTypedefs(true)
|
||||
|
||||
// Qt 6
|
||||
generate(
|
||||
"qt6",
|
||||
[]string{
|
||||
"/usr/include/x86_64-linux-gnu/qt6/QtCore",
|
||||
"/usr/include/x86_64-linux-gnu/qt6/QtGui",
|
||||
"/usr/include/x86_64-linux-gnu/qt6/QtWidgets",
|
||||
},
|
||||
*clang,
|
||||
strings.Fields("--std=c++17 "+pkgConfigCflags("Qt6Widgets")),
|
||||
*outDir,
|
||||
ClangMatchSameHeaderDefinitionOnly,
|
||||
)
|
||||
}
|
||||
|
||||
func generate(packageName string, srcDirs []string, clangBin string, cflags []string, outDir string, matcher ClangMatcher) {
|
||||
@ -170,8 +192,6 @@ func generate(packageName string, srcDirs []string, clangBin string, cflags []st
|
||||
preserve: make(map[string]*CppEnum),
|
||||
}
|
||||
|
||||
InsertTypedefs()
|
||||
|
||||
//
|
||||
// PASS 0 (Fill clang cache)
|
||||
//
|
||||
|
@ -4,6 +4,7 @@ RUN DEBIAN_FRONTEND=noninteractive apt-get update && \
|
||||
apt-get install --no-install-recommends -qyy \
|
||||
golang-go \
|
||||
qtbase5-dev \
|
||||
qt6-base-dev \
|
||||
libqscintilla2-qt5-dev \
|
||||
clang \
|
||||
git \
|
||||
|
6
docker/linux64-go1.19-qt6.4-dynamic.Dockerfile
Normal file
6
docker/linux64-go1.19-qt6.4-dynamic.Dockerfile
Normal file
@ -0,0 +1,6 @@
|
||||
FROM debian:bookworm
|
||||
|
||||
RUN DEBIAN_FRONTEND=noninteractive apt-get update && \
|
||||
apt-get install -qyy golang-go qt6-base-dev && \
|
||||
apt-get clean
|
||||
|
3
qt6/binding.go
Normal file
3
qt6/binding.go
Normal file
@ -0,0 +1,3 @@
|
||||
package qt6
|
||||
|
||||
type QSysInfo__Endian int
|
9
qt6/cflags_linux.go
Normal file
9
qt6/cflags_linux.go
Normal file
@ -0,0 +1,9 @@
|
||||
// +build linux,!android
|
||||
|
||||
package qt6
|
||||
|
||||
/*
|
||||
#cgo CFLAGS: -fPIC
|
||||
#cgo pkg-config: Qt6Widgets
|
||||
*/
|
||||
import "C"
|
Loading…
Reference in New Issue
Block a user