genbindings: preserve const/ptr attributes through typedefs

This commit is contained in:
mappu 2024-09-18 13:08:18 +12:00
parent db09326a76
commit eae85ac325
8 changed files with 91 additions and 91 deletions

View File

@ -84,11 +84,19 @@ func (p CppParameter) RenderTypeCabi() string {
ret += "*" 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 { 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 { if p.Const {
cppType = "const " + cppType cppType = "const " + cppType
@ -178,9 +186,13 @@ func emitParametersCABI2CppForwarding(params []CppParameter, indent string) (pre
return preamble, strings.Join(tmp, ", ") 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) { 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" { if p.ParameterType == "QString" {
// The CABI has accepted two parameters - need to convert to one real 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" preamble += indent + "}\n"
return preamble, nameprefix + "_QList" return preamble, nameprefix + "_QList"
} else if p.IsKnownEnum() { } else if p.IntType() || p.IsFlagType() || 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
castSrc := p.ParameterName castSrc := p.ParameterName
castType := p.RenderTypeQtCpp() castType := p.RenderTypeQtCpp()
@ -222,6 +224,10 @@ func emitCABI2CppForwarding(p CppParameter, indent string) (preamble string, for
castSrc = "*" + castSrc 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" || if p.ParameterType == "qint64" ||
p.ParameterType == "quint64" || p.ParameterType == "quint64" ||
p.ParameterType == "qlonglong" || p.ParameterType == "qlonglong" ||
@ -283,7 +289,7 @@ func emitAssignCppToCabi(assignExpression string, p CppParameter, rvalue string)
shouldReturn = shouldReturn[len(indent):] shouldReturn = shouldReturn[len(indent):]
namePrefix := p.ParameterName // TODO make unique, strip out [0], etc namePrefix := makeNamePrefix(p.ParameterName)
if p.ParameterType == "void" && !p.Pointer { if p.ParameterType == "void" && !p.Pointer {
shouldReturn = "" shouldReturn = ""
@ -366,15 +372,15 @@ func emitAssignCppToCabi(assignExpression string, p CppParameter, rvalue string)
// Elide temporary and emit directly from the rvalue // Elide temporary and emit directly from the rvalue
return indent + assignExpression + "new " + p.ParameterType + "(" + rvalue + ");\n" return indent + assignExpression + "new " + p.ParameterType + "(" + rvalue + ");\n"
} else if p.IsFlagType() { } else if p.IsFlagType() || p.IsKnownEnum() || p.QtCppOriginalType != nil {
// Needs an explicit int cast // Needs an explicit cast
shouldReturn = p.RenderTypeQtCpp() + " " + namePrefix + "_ret = " shouldReturn = p.RenderTypeQtCpp() + " " + namePrefix + "_ret = "
afterCall += indent + "" + assignExpression + "static_cast<int>(" + namePrefix + "_ret);\n"
} else if p.IsKnownEnum() || p.QtCppOriginalType != "" { if p.QtCppOriginalType != nil && p.QtCppOriginalType.Const != p.Const {
// Needs an explicit uintptr cast afterCall += indent + "" + assignExpression + "const_cast<" + p.RenderTypeCabi() + ">(static_cast<" + p.RenderTypeIntermediateCpp() + ">(" + namePrefix + "_ret));\n"
shouldReturn = p.RenderTypeQtCpp() + " " + namePrefix + "_ret = " } else {
afterCall += indent + "" + assignExpression + "static_cast<" + p.RenderTypeCabi() + ">(" + namePrefix + "_ret);\n" afterCall += indent + "" + assignExpression + "static_cast<" + p.RenderTypeCabi() + ">(" + namePrefix + "_ret);\n"
}
} else if p.Const { } else if p.Const {
shouldReturn += "(" + p.RenderTypeCabi() + ") " shouldReturn += "(" + p.RenderTypeCabi() + ") "

View File

@ -214,7 +214,7 @@ func (gfs *goFileState) emitParametersGo2CABIForwarding(m CppMethod) (preamble s
func (gfs *goFileState) emitParameterGo2CABIForwarding(p CppParameter) (preamble string, rvalue string) { 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" { if p.ParameterType == "QString" {
// Go: convert string -> miqt_string* // Go: convert string -> miqt_string*
@ -285,7 +285,7 @@ func (gfs *goFileState) emitCabiToGo(assignExpr string, rt CppParameter, rvalue
shouldReturn := "return " shouldReturn := "return "
afterword := "" afterword := ""
namePrefix := rt.ParameterName namePrefix := makeNamePrefix(rt.ParameterName)
if rt.ParameterType == "void" && !rt.Pointer { if rt.ParameterType == "void" && !rt.Pointer {
shouldReturn = "" 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 // Need to cast Cgo type to Go int type
// Optimize assignment to avoid temporary // Optimize assignment to avoid temporary
return assignExpr + "(" + rt.RenderTypeGo() + ")(" + rvalue + ")\n" return assignExpr + "(" + rt.RenderTypeGo() + ")(" + rvalue + ")\n"

View File

@ -133,16 +133,13 @@ func CheckComplexity(p CppParameter, isReturnType bool) error {
// std::seed_seq QRandom // std::seed_seq QRandom
return ErrTooComplex 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`) { if strings.Contains(p.ParameterType, `Iterator::value_type`) {
return ErrTooComplex // e.g. qcbormap return ErrTooComplex // e.g. qcbormap
} }
if strings.Contains(p.ParameterType, `::QPrivate`) { if strings.Contains(p.ParameterType, `::QPrivate`) {
return ErrTooComplex // e.g. QAbstractItemModel::QPrivateSignal 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() 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 "char16_t", // e.g. QChar() constructor overload, just unnecessary
"char32_t", // e.g. QDebug().operator<< overload, unnecessary "char32_t", // e.g. QDebug().operator<< overload, unnecessary
"wchar_t", // e.g. qstringview.h overloads, 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 "FILE", // e.g. qfile.h constructors
"qInternalCallback", // e.g. qnamespace.h "qInternalCallback", // e.g. qnamespace.h
"QGraphicsEffectSource", // e.g. used by qgraphicseffect.h, but the definition is in ???? "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. // generated headers (generated on Linux) with other OSes such as Windows.
// These methods will be blocked on non-Linux OSes. // These methods will be blocked on non-Linux OSes.
func LinuxWindowsCompatCheck(p CppParameter) bool { 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 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 true // uintptr_t-compatible on Linux, void* on Windows
} }
return false return false

View File

@ -37,25 +37,23 @@ func init() {
} }
type CppParameter struct { type CppParameter struct {
ParameterName string ParameterName string
ParameterType string ParameterType string
QtCppOriginalType string // If we rewrote QStringList->QList<String>, this field contains the original QStringList. Otherwise, it's blank Const bool
Const bool Pointer bool
Pointer bool PointerCount int
PointerCount int ByRef bool
ByRef bool Optional bool
Optional bool
}
func (p *CppParameter) AssignAlias(newType string) { QtCppOriginalType *CppParameter // If we rewrote QStringList->QList<String>, this field contains the original QStringList. Otherwise, it's blank
if p.QtCppOriginalType == "" {
p.QtCppOriginalType = p.ParameterType // Overwrite once only, at the earliest base type
}
p.ParameterType = newType
} }
func (p *CppParameter) ApplyTypedef(matchedUnderlyingType CppParameter) { 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 // 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 p.Const = p.Const || matchedUnderlyingType.Const
@ -78,20 +76,17 @@ func (p *CppParameter) ConstCast(isConst bool) CppParameter {
return ret return ret
} }
func (p *CppParameter) GetQtCppType() string { func (p *CppParameter) GetQtCppType() *CppParameter {
if p.QtCppOriginalType != "" { if p.QtCppOriginalType != nil {
return p.QtCppOriginalType return p.QtCppOriginalType
} }
return p.ParameterType return p
} }
func (p CppParameter) IsFlagType() bool { func (p CppParameter) IsFlagType() bool {
if strings.HasPrefix(p.ParameterType, `QFlags<`) { if strings.HasPrefix(p.ParameterType, `QFlags<`) ||
return true // This catches most cases through the typedef system strings.HasPrefix(p.GetQtCppType().ParameterType, `QFlags<`) {
}
if strings.HasPrefix(p.GetQtCppType(), `QFlags<`) {
return true // This catches most cases through the typedef system return true // This catches most cases through the typedef system
} }

View File

@ -18,12 +18,17 @@ func applyTypedefs(p CppParameter) CppParameter {
t2 := applyTypedefs(t) // recursive t2 := applyTypedefs(t) // recursive
// Wipe out so that RenderTypeQtCpp() does not see it // Wipe out so that RenderTypeQtCpp() does not see it
t2.QtCppOriginalType = "" t2.QtCppOriginalType = nil
// QListOf returns for either QList< or QVector< // QListOf returns for either QList< or QVector<
// Patch it up to the first < position and last character // Patch it up to the first < position and last character
bpos := strings.Index(p.ParameterType, `<`) 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 return p

View File

@ -735,43 +735,43 @@ QByteArray* QByteArray_FromPercentEncoding(QByteArray* pctEncoded) {
} }
char* QByteArray_Begin(QByteArray* self) { char* QByteArray_Begin(QByteArray* self) {
QByteArray::iterator* _ret = self->begin(); QByteArray::iterator _ret = self->begin();
return static_cast<char*>(_ret); return static_cast<char*>(_ret);
} }
const char* QByteArray_Begin2(const QByteArray* self) { const char* QByteArray_Begin2(const QByteArray* self) {
const QByteArray::const_iterator* _ret = self->begin(); QByteArray::const_iterator _ret = self->begin();
return static_cast<const char*>(_ret); return const_cast<const char*>(static_cast<const char*>(_ret));
} }
const char* QByteArray_Cbegin(const QByteArray* self) { const char* QByteArray_Cbegin(const QByteArray* self) {
const QByteArray::const_iterator* _ret = self->cbegin(); QByteArray::const_iterator _ret = self->cbegin();
return static_cast<const char*>(_ret); return const_cast<const char*>(static_cast<const char*>(_ret));
} }
const char* QByteArray_ConstBegin(const QByteArray* self) { const char* QByteArray_ConstBegin(const QByteArray* self) {
const QByteArray::const_iterator* _ret = self->constBegin(); QByteArray::const_iterator _ret = self->constBegin();
return static_cast<const char*>(_ret); return const_cast<const char*>(static_cast<const char*>(_ret));
} }
char* QByteArray_End(QByteArray* self) { char* QByteArray_End(QByteArray* self) {
QByteArray::iterator* _ret = self->end(); QByteArray::iterator _ret = self->end();
return static_cast<char*>(_ret); return static_cast<char*>(_ret);
} }
const char* QByteArray_End2(const QByteArray* self) { const char* QByteArray_End2(const QByteArray* self) {
const QByteArray::const_iterator* _ret = self->end(); QByteArray::const_iterator _ret = self->end();
return static_cast<const char*>(_ret); return const_cast<const char*>(static_cast<const char*>(_ret));
} }
const char* QByteArray_Cend(const QByteArray* self) { const char* QByteArray_Cend(const QByteArray* self) {
const QByteArray::const_iterator* _ret = self->cend(); QByteArray::const_iterator _ret = self->cend();
return static_cast<const char*>(_ret); return const_cast<const char*>(static_cast<const char*>(_ret));
} }
const char* QByteArray_ConstEnd(const QByteArray* self) { const char* QByteArray_ConstEnd(const QByteArray* self) {
const QByteArray::const_iterator* _ret = self->constEnd(); QByteArray::const_iterator _ret = self->constEnd();
return static_cast<const char*>(_ret); return const_cast<const char*>(static_cast<const char*>(_ret));
} }
void QByteArray_PushBack(QByteArray* self, char c) { void QByteArray_PushBack(QByteArray* self, char c) {

View File

@ -52,23 +52,23 @@ bool QRegion_IsNull(const QRegion* self) {
} }
QRect* QRegion_Begin(const QRegion* self) { QRect* QRegion_Begin(const QRegion* self) {
const QRegion::const_iterator* _ret = self->begin(); QRegion::const_iterator _ret = self->begin();
return static_cast<QRect*>(_ret); return const_cast<QRect*>(static_cast<const QRect*>(_ret));
} }
QRect* QRegion_Cbegin(const QRegion* self) { QRect* QRegion_Cbegin(const QRegion* self) {
const QRegion::const_iterator* _ret = self->cbegin(); QRegion::const_iterator _ret = self->cbegin();
return static_cast<QRect*>(_ret); return const_cast<QRect*>(static_cast<const QRect*>(_ret));
} }
QRect* QRegion_End(const QRegion* self) { QRect* QRegion_End(const QRegion* self) {
const QRegion::const_iterator* _ret = self->end(); QRegion::const_iterator _ret = self->end();
return static_cast<QRect*>(_ret); return const_cast<QRect*>(static_cast<const QRect*>(_ret));
} }
QRect* QRegion_Cend(const QRegion* self) { QRect* QRegion_Cend(const QRegion* self) {
const QRegion::const_iterator* _ret = self->cend(); QRegion::const_iterator _ret = self->cend();
return static_cast<QRect*>(_ret); return const_cast<QRect*>(static_cast<const QRect*>(_ret));
} }
bool QRegion_Contains(const QRegion* self, QPoint* p) { bool QRegion_Contains(const QRegion* self, QPoint* p) {

View File

@ -25,8 +25,8 @@ size_t QStringView_Size(const QStringView* self) {
} }
QChar* QStringView_Data(const QStringView* self) { QChar* QStringView_Data(const QStringView* self) {
const QStringView::const_pointer* _ret = self->data(); QStringView::const_pointer _ret = self->data();
return static_cast<QChar*>(_ret); return const_cast<QChar*>(static_cast<const QChar*>(_ret));
} }
QChar* QStringView_OperatorSubscript(const QStringView* self, size_t n) { 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) { QChar* QStringView_Begin(const QStringView* self) {
const QStringView::const_iterator* _ret = self->begin(); QStringView::const_iterator _ret = self->begin();
return static_cast<QChar*>(_ret); return const_cast<QChar*>(static_cast<const QChar*>(_ret));
} }
QChar* QStringView_End(const QStringView* self) { QChar* QStringView_End(const QStringView* self) {
const QStringView::const_iterator* _ret = self->end(); QStringView::const_iterator _ret = self->end();
return static_cast<QChar*>(_ret); return const_cast<QChar*>(static_cast<const QChar*>(_ret));
} }
QChar* QStringView_Cbegin(const QStringView* self) { QChar* QStringView_Cbegin(const QStringView* self) {
const QStringView::const_iterator* _ret = self->cbegin(); QStringView::const_iterator _ret = self->cbegin();
return static_cast<QChar*>(_ret); return const_cast<QChar*>(static_cast<const QChar*>(_ret));
} }
QChar* QStringView_Cend(const QStringView* self) { QChar* QStringView_Cend(const QStringView* self) {
const QStringView::const_iterator* _ret = self->cend(); QStringView::const_iterator _ret = self->cend();
return static_cast<QChar*>(_ret); return const_cast<QChar*>(static_cast<const QChar*>(_ret));
} }
bool QStringView_Empty(const QStringView* self) { bool QStringView_Empty(const QStringView* self) {