From f9a9b4a9b4f165b783c64b06797ff8cf0af152d1 Mon Sep 17 00:00:00 2001 From: mappu Date: Mon, 19 Aug 2024 19:42:34 +1200 Subject: [PATCH] genbindings: further work on exceptions --- cmd/genbindings/clang2il.go | 32 ++++++++++++-- cmd/genbindings/emitgo.go | 2 +- cmd/genbindings/exceptions.go | 81 ++++++++++++++++++++++++++--------- 3 files changed, 91 insertions(+), 24 deletions(-) diff --git a/cmd/genbindings/clang2il.go b/cmd/genbindings/clang2il.go index 41901ae..c8d6946 100644 --- a/cmd/genbindings/clang2il.go +++ b/cmd/genbindings/clang2il.go @@ -510,8 +510,10 @@ func parseSingleTypeString(p string) CppParameter { tokens := strings.Split(strings.TrimSpace(p), " ") insert := CppParameter{} for _, tok := range tokens { + if tok == "" { continue // extra space + } else if tok == "const" || tok == "*const" { // *const happens for QPixmap, clang reports `const char *const *` which // isn't even valid syntax @@ -519,17 +521,41 @@ func parseSingleTypeString(p string) CppParameter { } else if tok == "&" { // U+0026 insert.ByRef = true + } else if tok == "*" { insert.Pointer = true + } else if tok == "WId" { // Transform typedef insert.ParameterType += " uintptr_t" + + } else if tok == "Q_PID" { + // Transform typedef + // This is a uint64 PID on Linux/mac and a PROCESS_INFORMATION* on Windows + // A uintptr should be tolerable for both cases until we do better + // @ref https://doc.qt.io/qt-5/qprocess.html#Q_PID-typedef + insert.ParameterType += " uintptr_t" + } else if tok == "QStringList" { insert.ParameterType += " QList" - } else if len(tok) > 4 && strings.HasSuffix(tok, "List") && tok != "QTextList" { + + } else if len(tok) > 4 && strings.HasSuffix(tok, "List") { + // Classes ending in --List are usually better represented as a QList + // type directly, so that the binding uses proper Go slices // Typedef e.g. QObjectList - // QObjectList is a pointer, but QStringList is a whole custom class - insert.ParameterType += " QList<" + tok[0:len(tok)-4] + " *>" + switch tok { + case "QModelIndexList": + // These types are defined as a QList of values + insert.ParameterType += " QList" + case "QTextList": + // This is really a custom class, preserve as-is + insert.ParameterType += " " + tok + default: + // These types are defined as a QList of pointers. + // QList. This is the most common case + insert.ParameterType += " QList<" + tok[0:len(tok)-4] + " *>" + } + } else { // Valid part of the type name insert.ParameterType += " " + tok diff --git a/cmd/genbindings/emitgo.go b/cmd/genbindings/emitgo.go index e3a3a98..edcf85e 100644 --- a/cmd/genbindings/emitgo.go +++ b/cmd/genbindings/emitgo.go @@ -11,7 +11,7 @@ import ( func goReservedWord(s string) bool { switch s { - case "default", "const", "func", "var", "type", "len", "new", "copy", "import", "range": + case "default", "const", "func", "var", "type", "len", "new", "copy", "import", "range", "string", "map", "int", "select": return true default: return false diff --git a/cmd/genbindings/exceptions.go b/cmd/genbindings/exceptions.go index d63f6fa..56f816c 100644 --- a/cmd/genbindings/exceptions.go +++ b/cmd/genbindings/exceptions.go @@ -1,10 +1,41 @@ package main import ( + "path/filepath" "strings" ) func AllowHeader(fullpath string) bool { + fname := filepath.Base(fullpath) + + if strings.HasSuffix(fname, `_impl.h`) { + return false // Not meant to be imported + } + + fname_lc := strings.ToLower(fname) + if strings.Contains(fname_lc, `opengl`) || strings.Contains(fname_lc, `vulkan`) { + return false // Too hard + } + + switch fname { + case // QtCore + "qatomic_bootstrap.h", + "qatomic_cxx11.h", + "qatomic_msvc.h", + "qgenericatomic.h", // Clang error + "qt_windows.h", // Clang error + "qmaccocoaviewcontainer_mac.h", // Needs NSView* headers. TODO allow with darwin build tag + "qmacnativewidget_mac.h", // Needs NSView* headers. TODO allow with darwin build tag + "qaccessible.h", // Almost everything in here is virtual + "qaccessiblebridge.h", // Almost everything in here is virtual + "qaccessibleobject.h", // Almost everything in here is virtual + "qaccessibleplugin.h", // Almost everything in here is virtual + "qstring.h", // QString does not exist in this binding + "qlist.h", // QList does not exist in this binding + "qvector.h": // QVector does not exist in this binding + return false + } + return true } @@ -53,10 +84,11 @@ func AllowClass(className string) bool { switch className { case - "QException", // Extends std::exception, too hard - "QItemSelection", // Extends a QList<>, too hard - "QXmlStreamAttributes", // Extends a QList<>, too hard - "QPolygon", "QPolygonF": // Extends a QVector template class, too hard + "QTextStreamManipulator", // Only seems to contain garbage methods + "QException", // Extends std::exception, too hard + "QItemSelection", // Extends a QList<>, too hard + "QXmlStreamAttributes", // Extends a QList<>, too hard + "QPolygon", "QPolygonF": // Extends a QVector template class, too hard return false } @@ -80,6 +112,10 @@ func CheckComplexity(p CppParameter) error { } } + if strings.HasPrefix(p.ParameterType, "StringResult<") { + return ErrTooComplex // e.g. qcborstreamreader.h + } + switch p.ParameterType { case "QList", // e.g. QVariant constructor - this has a deleted copy-constructor so we can't get it over the CABI boundary by value @@ -88,22 +124,27 @@ func CheckComplexity(p CppParameter) error { "QLatin1String", "QStringView", // e.g. QColor constructors and QColor::SetNamedColor() overloads. These are usually optional alternatives to QString "QStringRef", // e.g. QLocale::toLongLong and similar overloads. As above "QGradientStop", "QGradientStops", // QPair<>-related types, but we can't see through the typedef to block based on QPair alone - "void **", // e.g. qobjectdefs.h QMetaObject->Activate() - "QGraphicsItem **", // e.g. QGraphicsItem::IsBlockedByModalPanel() overload - "char *&", // e.g. QDataStream.operator<<() - "qfloat16", // e.g. QDataStream - there is no such half-float type in C or Go - "char16_t", // e.g. QChar() constructor overload, just unnecessary - "char32_t", // e.g. QDebug().operator<< overload, unnecessary - "picture_io_handler", // e.g. QPictureIO::DefineIOHandler callback function - "QPlatformNativeInterface", // e.g. QGuiApplication::platformNativeInterface(). Private type, could probably expose as uintptr. n.b. Changes in Qt6 - "QFunctionPointer", // e.g. QGuiApplication_PlatformFunction - "QGraphicsEffectSource", // e.g. used by qgraphicseffect.h, but the definition is in ???? - "QAbstractUndoItem", // e.g. Defined in qtextdocument.h - "QTextObjectInterface", // e.g. qabstracttextdocumentlayout.h - "QPlatformPixmap", // e.g. qpixmap.h. as below - "QPlatformScreen", // e.g. qscreen.h. as below - "QPlatformSurface", // e.g. qsurface.h. as below - "QPlatformMenu": // e.g. QMenu_PlatformMenu. Defined in the QPA, could probably expose as uintptr + "void **", // e.g. qobjectdefs.h QMetaObject->Activate() + "QGraphicsItem **", // e.g. QGraphicsItem::IsBlockedByModalPanel() overload + "char *&", // e.g. QDataStream.operator<<() + "qfloat16", // e.g. QDataStream - there is no such half-float type in C or Go + "char16_t", // e.g. QChar() constructor overload, just unnecessary + "char32_t", // e.g. QDebug().operator<< overload, unnecessary + "picture_io_handler", // e.g. QPictureIO::DefineIOHandler callback function + "QPlatformNativeInterface", // e.g. QGuiApplication::platformNativeInterface(). Private type, could probably expose as uintptr. n.b. Changes in Qt6 + "QFunctionPointer", // e.g. QGuiApplication_PlatformFunction + "QGraphicsEffectSource", // e.g. used by qgraphicseffect.h, but the definition is in ???? + "QAbstractUndoItem", // e.g. Defined in qtextdocument.h + "QTextObjectInterface", // e.g. qabstracttextdocumentlayout.h + "QXmlStreamEntityDeclarations", // e.g. qxmlstream.h. The class definition was blacklisted for ???? reason so don't allow it as a parameter either + "QXmlStreamNamespaceDeclarations", // e.g. qxmlstream.h. As above + "QXmlStreamNotationDeclarations", // e.g. qxmlstream.h. As above + "QVariantMap", // e.g. qcbormap.h + "QVariantHash", // e.g. qcbormap.h + "QPlatformPixmap", // e.g. qpixmap.h. as below + "QPlatformScreen", // e.g. qscreen.h. as below + "QPlatformSurface", // e.g. qsurface.h. as below + "QPlatformMenu": // e.g. QMenu_PlatformMenu. Defined in the QPA, could probably expose as uintptr return ErrTooComplex }