From e020b8d97d59e6c9472e48d2626192f24ecc61a1 Mon Sep 17 00:00:00 2001 From: Uwe Siems Date: Thu, 12 Nov 2026 18:03:36 +0100 Subject: [PATCH 1/3] Do not create shell classes because of protected functions or field accessors - those were not created in the shell classes, and the shell classes were not used for that (this might be a remnant of the original Java wrapper generator). Instead require additionally that the destructor is virtual. Otherwise the wrong destructor will be called for objects created from Python. --- generator/abstractmetalang.cpp | 9 ++++++++- generator/abstractmetalang.h | 1 + 2 files changed, 9 insertions(+), 1 deletion(-) diff --git a/generator/abstractmetalang.cpp b/generator/abstractmetalang.cpp index d565e7266..da3170b28 100644 --- a/generator/abstractmetalang.cpp +++ b/generator/abstractmetalang.cpp @@ -1154,8 +1154,10 @@ bool AbstractMetaClass::hasProtectedFunctions() const bool AbstractMetaClass::generateShellClass() const { return typeEntry()->shouldCreateShell() + // require that classes that get a shell have a virtual destructor + // (required for proper working of derived class) && (m_force_shell_class - || (!isFinal() && (hasVirtualFunctions() || hasProtectedFunctions() || hasFieldAccessors()))); + || (!isFinal() && hasVirtualDestructor() && (hasVirtualFunctions() || hasProtectedConstructors()))); } QPropertySpec* AbstractMetaClass::propertySpecForRead(const QString& name) const @@ -1315,6 +1317,11 @@ bool AbstractMetaClass::hasConstructors() const return queryFunctions(Constructors).size() != 0; } +bool AbstractMetaClass::hasProtectedConstructors() const +{ + return queryFunctions(Constructors | WasProtected).size() != 0; +} + void AbstractMetaClass::addDefaultConstructor() { AbstractMetaFunction* f = new AbstractMetaFunction; diff --git a/generator/abstractmetalang.h b/generator/abstractmetalang.h index 6e62499b7..59a2ad321 100644 --- a/generator/abstractmetalang.h +++ b/generator/abstractmetalang.h @@ -697,6 +697,7 @@ class AbstractMetaClass : public AbstractMetaAttributes bool hasSignal(const AbstractMetaFunction* f) const; bool hasConstructors() const; + bool hasProtectedConstructors() const; void addDefaultConstructor(); From fecc863be253dc03a8c7529b2fc98d88f95c86ac Mon Sep 17 00:00:00 2001 From: Uwe Siems Date: Thu, 12 Nov 2026 18:04:39 +0100 Subject: [PATCH 2/3] Field accessors are only generated for public members (this method isn't currently used anymore, though) --- generator/abstractmetalang.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/generator/abstractmetalang.cpp b/generator/abstractmetalang.cpp index da3170b28..c15d80106 100644 --- a/generator/abstractmetalang.cpp +++ b/generator/abstractmetalang.cpp @@ -1066,7 +1066,7 @@ void AbstractMetaClass::setFunctions(const AbstractMetaFunctionList& functions) bool AbstractMetaClass::hasFieldAccessors() const { for (const AbstractMetaField* field : fields()) { - if (field->getter() || field->setter()) + if (field->isPublic() && (field->getter() || field->setter())) return true; } From 48ca617bd7795a14730318642f1133e28b8950e8 Mon Sep 17 00:00:00 2001 From: Uwe Siems Date: Thu, 12 Nov 2026 18:06:57 +0100 Subject: [PATCH 3/3] Remember/re-use the result of AbstractMetaClass::generateShellClass() --- generator/shellheadergenerator.cpp | 10 +++++----- generator/shellimplgenerator.cpp | 8 +++----- 2 files changed, 8 insertions(+), 10 deletions(-) diff --git a/generator/shellheadergenerator.cpp b/generator/shellheadergenerator.cpp index ce8fb6448..d0ef5a7a7 100644 --- a/generator/shellheadergenerator.cpp +++ b/generator/shellheadergenerator.cpp @@ -135,7 +135,8 @@ void ShellHeaderGenerator::write(QTextStream& s, const AbstractMetaClass* meta_c } // Shell------------------------------------------------------------------- - if (meta_class->generateShellClass() && !ctors.isEmpty()) { + bool generateShell = meta_class->generateShellClass() && !ctors.isEmpty(); + if (generateShell) { AbstractMetaFunctionList virtualsForShell = getVirtualFunctionsForShell(meta_class); @@ -348,12 +349,12 @@ void ShellHeaderGenerator::write(QTextStream& s, const AbstractMetaClass* meta_c } } s << "public Q_SLOTS:" << Qt::endl; - if (meta_class->generateShellClass() || !meta_class->isAbstract()) { + if (generateShell || !meta_class->isAbstract()) { bool copyConstructorSeen = false; bool defaultConstructorSeen = false; for (const AbstractMetaFunction* fun : ctors) { - if (fun->isAbstract() || (!meta_class->generateShellClass() && !fun->isPublic())) { + if (fun->isAbstract() || (!generateShell && !fun->isPublic())) { continue; } @@ -373,8 +374,7 @@ void ShellHeaderGenerator::write(QTextStream& s, const AbstractMetaClass* meta_c if (meta_class->typeEntry()->isValue() && !copyConstructorSeen && defaultConstructorSeen && !meta_class->typeEntry()->hasNoCopy()) { - QString className = - meta_class->generateShellClass() ? shellClassName(meta_class) : meta_class->qualifiedCppName(); + QString className = generateShell ? shellClassName(meta_class) : meta_class->qualifiedCppName(); s << meta_class->qualifiedCppName() << "* new_" << meta_class->name() << "(const " << meta_class->qualifiedCppName() << "& other) {" << Qt::endl; s << className << "* a = new " << className << "();" << Qt::endl; diff --git a/generator/shellimplgenerator.cpp b/generator/shellimplgenerator.cpp index 38d18d3c1..f3d8c3f66 100644 --- a/generator/shellimplgenerator.cpp +++ b/generator/shellimplgenerator.cpp @@ -228,11 +228,11 @@ void ShellImplGenerator::write(QTextStream& s, const AbstractMetaClass* meta_cla } } - if (meta_class->generateShellClass() || !meta_class->isAbstract()) { + if (generateShell || !meta_class->isAbstract()) { // write constructors for (const AbstractMetaFunction* ctor : ctors) { - if (ctor->isAbstract() || (!meta_class->generateShellClass() && !ctor->isPublic())) { + if (ctor->isAbstract() || (!generateShell && !ctor->isPublic())) { continue; } @@ -241,8 +241,7 @@ void ShellImplGenerator::write(QTextStream& s, const AbstractMetaClass* meta_cla writeFunctionSignature(s, ctor, 0, "new_", Option(AddOwnershipTemplates | ShowStatic)); s << Qt::endl; s << "{ " << Qt::endl; - s << "return new " - << (meta_class->generateShellClass() ? shellClassName(meta_class) : meta_class->qualifiedCppName()) << "("; + s << "return new " << (generateShell ? shellClassName(meta_class) : meta_class->qualifiedCppName()) << "("; AbstractMetaArgumentList args = ctor->arguments(); for (int i = 0; i < args.size(); ++i) { if (i > 0) @@ -333,7 +332,6 @@ void ShellImplGenerator::write(QTextStream& s, const AbstractMetaClass* meta_cla } } else { if (fun->wasProtected()) { - //|| (fun->isVirtual() && meta_class->typeEntry()->shouldCreatePromoter())) { s << " ((" << promoterClassName(meta_class) << "*)theWrappedObject)->promoted_"; } else { s << " theWrappedObject->";