diff --git a/cmd/genbindings/emitcabi.go b/cmd/genbindings/emitcabi.go index a7446f6..006da57 100644 --- a/cmd/genbindings/emitcabi.go +++ b/cmd/genbindings/emitcabi.go @@ -84,11 +84,19 @@ func (p CppParameter) RenderTypeCabi() string { ret += "*" } - return ret // ignore const + return ret } +// RenderTypeQtCpp renders the Qt C++ type in the original form from the function +// definition, before any typedefs or transformations were applied. func (p CppParameter) RenderTypeQtCpp() string { - cppType := p.GetQtCppType() + return p.GetQtCppType().RenderTypeIntermediateCpp() +} + +// RenderTypeIntermediateCpp renders the Qt C++ type WITHOUT resolving the +// interior QtCppOriginalType. This is used for intermediate const_cast<>s. +func (p CppParameter) RenderTypeIntermediateCpp() string { + cppType := p.ParameterType if p.Const { cppType = "const " + cppType @@ -178,9 +186,13 @@ func emitParametersCABI2CppForwarding(params []CppParameter, indent string) (pre return preamble, strings.Join(tmp, ", ") } +func makeNamePrefix(in string) string { + return strings.Replace(strings.Replace(in, `[`, `_`, -1), `]`, "", -1) +} + func emitCABI2CppForwarding(p CppParameter, indent string) (preamble string, forwarding string) { - nameprefix := strings.Replace(strings.Replace(p.ParameterName, `[`, `_`, -1), `]`, "", -1) + nameprefix := makeNamePrefix(p.ParameterName) if p.ParameterType == "QString" { // The CABI has accepted two parameters - need to convert to one real QString @@ -204,17 +216,7 @@ func emitCABI2CppForwarding(p CppParameter, indent string) (preamble string, for preamble += indent + "}\n" return preamble, nameprefix + "_QList" - } else if p.IsKnownEnum() { - // The enums are projected in CABI as their underlying int types. - // Cast to the Qt enum type so that we get the correct overload - return preamble, "static_cast<" + p.RenderTypeQtCpp() + ">(" + p.ParameterName + ")" - - } else if p.IsFlagType() { - return preamble, "static_cast<" + p.RenderTypeQtCpp() + ">(" + p.ParameterName + ")" - - } else if p.IntType() { - // Use the raw ParameterType to select an explicit integer overload - // Don't use RenderTypeCabi() since it canonicalizes some int types for CABI + } else if p.IntType() || p.IsFlagType() || p.IsKnownEnum() { castSrc := p.ParameterName castType := p.RenderTypeQtCpp() @@ -222,6 +224,10 @@ func emitCABI2CppForwarding(p CppParameter, indent string) (preamble string, for castSrc = "*" + castSrc } + if p.QtCppOriginalType != nil && p.QtCppOriginalType.Const != p.Const { + return preamble, "static_cast<" + p.RenderTypeQtCpp() + ">(const_cast<" + p.RenderTypeIntermediateCpp() + ">(" + p.ParameterName + "))" + } + if p.ParameterType == "qint64" || p.ParameterType == "quint64" || p.ParameterType == "qlonglong" || @@ -283,7 +289,7 @@ func emitAssignCppToCabi(assignExpression string, p CppParameter, rvalue string) shouldReturn = shouldReturn[len(indent):] - namePrefix := p.ParameterName // TODO make unique, strip out [0], etc + namePrefix := makeNamePrefix(p.ParameterName) if p.ParameterType == "void" && !p.Pointer { shouldReturn = "" @@ -366,15 +372,15 @@ func emitAssignCppToCabi(assignExpression string, p CppParameter, rvalue string) // Elide temporary and emit directly from the rvalue return indent + assignExpression + "new " + p.ParameterType + "(" + rvalue + ");\n" - } else if p.IsFlagType() { - // Needs an explicit int cast + } else if p.IsFlagType() || p.IsKnownEnum() || p.QtCppOriginalType != nil { + // Needs an explicit cast shouldReturn = p.RenderTypeQtCpp() + " " + namePrefix + "_ret = " - afterCall += indent + "" + assignExpression + "static_cast(" + namePrefix + "_ret);\n" - } else if p.IsKnownEnum() || p.QtCppOriginalType != "" { - // Needs an explicit uintptr cast - shouldReturn = p.RenderTypeQtCpp() + " " + namePrefix + "_ret = " - afterCall += indent + "" + assignExpression + "static_cast<" + p.RenderTypeCabi() + ">(" + namePrefix + "_ret);\n" + if p.QtCppOriginalType != nil && p.QtCppOriginalType.Const != p.Const { + afterCall += indent + "" + assignExpression + "const_cast<" + p.RenderTypeCabi() + ">(static_cast<" + p.RenderTypeIntermediateCpp() + ">(" + namePrefix + "_ret));\n" + } else { + afterCall += indent + "" + assignExpression + "static_cast<" + p.RenderTypeCabi() + ">(" + namePrefix + "_ret);\n" + } } else if p.Const { shouldReturn += "(" + p.RenderTypeCabi() + ") " diff --git a/cmd/genbindings/emitgo.go b/cmd/genbindings/emitgo.go index 82afadb..ee42a6c 100644 --- a/cmd/genbindings/emitgo.go +++ b/cmd/genbindings/emitgo.go @@ -214,7 +214,7 @@ func (gfs *goFileState) emitParametersGo2CABIForwarding(m CppMethod) (preamble s func (gfs *goFileState) emitParameterGo2CABIForwarding(p CppParameter) (preamble string, rvalue string) { - nameprefix := strings.Replace(strings.Replace(p.ParameterName, `[`, `_`, -1), `]`, "", -1) + nameprefix := makeNamePrefix(p.ParameterName) if p.ParameterType == "QString" { // Go: convert string -> miqt_string* @@ -285,7 +285,7 @@ func (gfs *goFileState) emitCabiToGo(assignExpr string, rt CppParameter, rvalue shouldReturn := "return " afterword := "" - namePrefix := rt.ParameterName + namePrefix := makeNamePrefix(rt.ParameterName) if rt.ParameterType == "void" && !rt.Pointer { shouldReturn = "" @@ -370,7 +370,7 @@ func (gfs *goFileState) emitCabiToGo(assignExpr string, rt CppParameter, rvalue } } - } else if rt.IntType() || rt.IsKnownEnum() || rt.IsFlagType() || rt.ParameterType == "bool" || rt.QtCppOriginalType != "" { + } else if rt.IntType() || rt.IsKnownEnum() || rt.IsFlagType() || rt.ParameterType == "bool" || rt.QtCppOriginalType != nil { // Need to cast Cgo type to Go int type // Optimize assignment to avoid temporary return assignExpr + "(" + rt.RenderTypeGo() + ")(" + rvalue + ")\n" diff --git a/cmd/genbindings/exceptions.go b/cmd/genbindings/exceptions.go index bc739fa..d5616f1 100644 --- a/cmd/genbindings/exceptions.go +++ b/cmd/genbindings/exceptions.go @@ -133,16 +133,13 @@ func CheckComplexity(p CppParameter, isReturnType bool) error { // std::seed_seq QRandom return ErrTooComplex } - if strings.Contains(p.ParameterType, `::reverse_iterator`) || strings.Contains(p.ParameterType, `::const_reverse_iterator`) { - return ErrTooComplex // e.g. qbytearray.h - } if strings.Contains(p.ParameterType, `Iterator::value_type`) { return ErrTooComplex // e.g. qcbormap } if strings.Contains(p.ParameterType, `::QPrivate`) { return ErrTooComplex // e.g. QAbstractItemModel::QPrivateSignal } - if strings.Contains(p.GetQtCppType(), `::DataPtr`) { + if strings.Contains(p.GetQtCppType().ParameterType, `::DataPtr`) { return ErrTooComplex // e.g. QImage::data_ptr() } @@ -191,9 +188,6 @@ func CheckComplexity(p CppParameter, isReturnType bool) error { "char16_t", // e.g. QChar() constructor overload, just unnecessary "char32_t", // e.g. QDebug().operator<< overload, unnecessary "wchar_t", // e.g. qstringview.h overloads, unnecessary - "QStringView::const_pointer", // e.g. qstringview.h data() - "QStringView::const_iterator", // e.g. qstringview.h - "QStringView::value_type", // e.g. qstringview.h "FILE", // e.g. qfile.h constructors "qInternalCallback", // e.g. qnamespace.h "QGraphicsEffectSource", // e.g. used by qgraphicseffect.h, but the definition is in ???? @@ -233,11 +227,11 @@ func CheckComplexity(p CppParameter, isReturnType bool) error { // generated headers (generated on Linux) with other OSes such as Windows. // These methods will be blocked on non-Linux OSes. func LinuxWindowsCompatCheck(p CppParameter) bool { - if p.GetQtCppType() == "Q_PID" { + if p.GetQtCppType().ParameterType == "Q_PID" { return true // int64 on Linux, _PROCESS_INFORMATION* on Windows } - if p.GetQtCppType() == "QSocketDescriptor::DescriptorType" { + if p.GetQtCppType().ParameterType == "QSocketDescriptor::DescriptorType" { return true // uintptr_t-compatible on Linux, void* on Windows } return false diff --git a/cmd/genbindings/intermediate.go b/cmd/genbindings/intermediate.go index 4069b03..2cb80d9 100644 --- a/cmd/genbindings/intermediate.go +++ b/cmd/genbindings/intermediate.go @@ -37,25 +37,23 @@ func init() { } type CppParameter struct { - ParameterName string - ParameterType string - QtCppOriginalType string // If we rewrote QStringList->QList, this field contains the original QStringList. Otherwise, it's blank - Const bool - Pointer bool - PointerCount int - ByRef bool - Optional bool -} + ParameterName string + ParameterType string + Const bool + Pointer bool + PointerCount int + ByRef bool + Optional bool -func (p *CppParameter) AssignAlias(newType string) { - if p.QtCppOriginalType == "" { - p.QtCppOriginalType = p.ParameterType // Overwrite once only, at the earliest base type - } - p.ParameterType = newType + QtCppOriginalType *CppParameter // If we rewrote QStringList->QList, this field contains the original QStringList. Otherwise, it's blank } func (p *CppParameter) ApplyTypedef(matchedUnderlyingType CppParameter) { - p.AssignAlias(matchedUnderlyingType.ParameterType) + if p.QtCppOriginalType == nil { + tmp := *p // Copy + p.QtCppOriginalType = &tmp // Overwrite once only, at the earliest base type + } + p.ParameterType = matchedUnderlyingType.ParameterType // If this was a pointer to a typedef'd type, or a typedef of a pointer type, we need to preserve that p.Const = p.Const || matchedUnderlyingType.Const @@ -78,20 +76,17 @@ func (p *CppParameter) ConstCast(isConst bool) CppParameter { return ret } -func (p *CppParameter) GetQtCppType() string { - if p.QtCppOriginalType != "" { +func (p *CppParameter) GetQtCppType() *CppParameter { + if p.QtCppOriginalType != nil { return p.QtCppOriginalType } - return p.ParameterType + return p } func (p CppParameter) IsFlagType() bool { - if strings.HasPrefix(p.ParameterType, `QFlags<`) { - return true // This catches most cases through the typedef system - } - - if strings.HasPrefix(p.GetQtCppType(), `QFlags<`) { + if strings.HasPrefix(p.ParameterType, `QFlags<`) || + strings.HasPrefix(p.GetQtCppType().ParameterType, `QFlags<`) { return true // This catches most cases through the typedef system } diff --git a/cmd/genbindings/transformtypedefs.go b/cmd/genbindings/transformtypedefs.go index 307c0bd..f5691f9 100644 --- a/cmd/genbindings/transformtypedefs.go +++ b/cmd/genbindings/transformtypedefs.go @@ -18,12 +18,17 @@ func applyTypedefs(p CppParameter) CppParameter { t2 := applyTypedefs(t) // recursive // Wipe out so that RenderTypeQtCpp() does not see it - t2.QtCppOriginalType = "" + t2.QtCppOriginalType = nil // QListOf returns for either QList< or QVector< // Patch it up to the first < position and last character bpos := strings.Index(p.ParameterType, `<`) - p.AssignAlias(p.ParameterType[0:bpos] + `<` + t2.RenderTypeQtCpp() + `>`) + + if p.QtCppOriginalType == nil { + tmp := p // copy + p.QtCppOriginalType = &tmp + } + p.ParameterType = p.ParameterType[0:bpos] + `<` + t2.RenderTypeQtCpp() + `>` } return p diff --git a/qt/gen_qbytearray.cpp b/qt/gen_qbytearray.cpp index 79b287c..ec77736 100644 --- a/qt/gen_qbytearray.cpp +++ b/qt/gen_qbytearray.cpp @@ -735,43 +735,43 @@ QByteArray* QByteArray_FromPercentEncoding(QByteArray* pctEncoded) { } char* QByteArray_Begin(QByteArray* self) { - QByteArray::iterator* _ret = self->begin(); + QByteArray::iterator _ret = self->begin(); return static_cast(_ret); } const char* QByteArray_Begin2(const QByteArray* self) { - const QByteArray::const_iterator* _ret = self->begin(); - return static_cast(_ret); + QByteArray::const_iterator _ret = self->begin(); + return const_cast(static_cast(_ret)); } const char* QByteArray_Cbegin(const QByteArray* self) { - const QByteArray::const_iterator* _ret = self->cbegin(); - return static_cast(_ret); + QByteArray::const_iterator _ret = self->cbegin(); + return const_cast(static_cast(_ret)); } const char* QByteArray_ConstBegin(const QByteArray* self) { - const QByteArray::const_iterator* _ret = self->constBegin(); - return static_cast(_ret); + QByteArray::const_iterator _ret = self->constBegin(); + return const_cast(static_cast(_ret)); } char* QByteArray_End(QByteArray* self) { - QByteArray::iterator* _ret = self->end(); + QByteArray::iterator _ret = self->end(); return static_cast(_ret); } const char* QByteArray_End2(const QByteArray* self) { - const QByteArray::const_iterator* _ret = self->end(); - return static_cast(_ret); + QByteArray::const_iterator _ret = self->end(); + return const_cast(static_cast(_ret)); } const char* QByteArray_Cend(const QByteArray* self) { - const QByteArray::const_iterator* _ret = self->cend(); - return static_cast(_ret); + QByteArray::const_iterator _ret = self->cend(); + return const_cast(static_cast(_ret)); } const char* QByteArray_ConstEnd(const QByteArray* self) { - const QByteArray::const_iterator* _ret = self->constEnd(); - return static_cast(_ret); + QByteArray::const_iterator _ret = self->constEnd(); + return const_cast(static_cast(_ret)); } void QByteArray_PushBack(QByteArray* self, char c) { diff --git a/qt/gen_qregion.cpp b/qt/gen_qregion.cpp index b1eb9cb..ff1e4a0 100644 --- a/qt/gen_qregion.cpp +++ b/qt/gen_qregion.cpp @@ -52,23 +52,23 @@ bool QRegion_IsNull(const QRegion* self) { } QRect* QRegion_Begin(const QRegion* self) { - const QRegion::const_iterator* _ret = self->begin(); - return static_cast(_ret); + QRegion::const_iterator _ret = self->begin(); + return const_cast(static_cast(_ret)); } QRect* QRegion_Cbegin(const QRegion* self) { - const QRegion::const_iterator* _ret = self->cbegin(); - return static_cast(_ret); + QRegion::const_iterator _ret = self->cbegin(); + return const_cast(static_cast(_ret)); } QRect* QRegion_End(const QRegion* self) { - const QRegion::const_iterator* _ret = self->end(); - return static_cast(_ret); + QRegion::const_iterator _ret = self->end(); + return const_cast(static_cast(_ret)); } QRect* QRegion_Cend(const QRegion* self) { - const QRegion::const_iterator* _ret = self->cend(); - return static_cast(_ret); + QRegion::const_iterator _ret = self->cend(); + return const_cast(static_cast(_ret)); } bool QRegion_Contains(const QRegion* self, QPoint* p) { diff --git a/qt/gen_qstringview.cpp b/qt/gen_qstringview.cpp index 2d9ddeb..64e6e84 100644 --- a/qt/gen_qstringview.cpp +++ b/qt/gen_qstringview.cpp @@ -25,8 +25,8 @@ size_t QStringView_Size(const QStringView* self) { } QChar* QStringView_Data(const QStringView* self) { - const QStringView::const_pointer* _ret = self->data(); - return static_cast(_ret); + QStringView::const_pointer _ret = self->data(); + return const_cast(static_cast(_ret)); } QChar* QStringView_OperatorSubscript(const QStringView* self, size_t n) { @@ -164,23 +164,23 @@ double QStringView_ToDouble(const QStringView* self) { } QChar* QStringView_Begin(const QStringView* self) { - const QStringView::const_iterator* _ret = self->begin(); - return static_cast(_ret); + QStringView::const_iterator _ret = self->begin(); + return const_cast(static_cast(_ret)); } QChar* QStringView_End(const QStringView* self) { - const QStringView::const_iterator* _ret = self->end(); - return static_cast(_ret); + QStringView::const_iterator _ret = self->end(); + return const_cast(static_cast(_ret)); } QChar* QStringView_Cbegin(const QStringView* self) { - const QStringView::const_iterator* _ret = self->cbegin(); - return static_cast(_ret); + QStringView::const_iterator _ret = self->cbegin(); + return const_cast(static_cast(_ret)); } QChar* QStringView_Cend(const QStringView* self) { - const QStringView::const_iterator* _ret = self->cend(); - return static_cast(_ret); + QStringView::const_iterator _ret = self->cend(); + return const_cast(static_cast(_ret)); } bool QStringView_Empty(const QStringView* self) {