diff options
4 files changed, 52 insertions, 13 deletions
diff --git a/sources/shiboken6/ApiExtractor/abstractmetalang.cpp b/sources/shiboken6/ApiExtractor/abstractmetalang.cpp index abc939dcf..47249b648 100644 --- a/sources/shiboken6/ApiExtractor/abstractmetalang.cpp +++ b/sources/shiboken6/ApiExtractor/abstractmetalang.cpp @@ -42,6 +42,8 @@ #include <QtCore/QDebug> +#include <algorithm> + bool function_sorter(const AbstractMetaFunctionCPtr &a, const AbstractMetaFunctionCPtr &b) { return a->signature() < b->signature(); @@ -286,6 +288,12 @@ void AbstractMetaClass::addField(const AbstractMetaField &field) d->m_fields << field; } +bool AbstractMetaClass::hasStaticFields() const +{ + return std::any_of(d->m_fields.cbegin(), d->m_fields.cend(), + [](const AbstractMetaField &f) { return f.isStatic(); }); +} + void AbstractMetaClass::sortFunctions() { std::sort(d->m_functions.begin(), d->m_functions.end(), function_sorter); diff --git a/sources/shiboken6/ApiExtractor/abstractmetalang.h b/sources/shiboken6/ApiExtractor/abstractmetalang.h index 3626ba469..5a155c6fc 100644 --- a/sources/shiboken6/ApiExtractor/abstractmetalang.h +++ b/sources/shiboken6/ApiExtractor/abstractmetalang.h @@ -123,6 +123,7 @@ public: AbstractMetaFieldList &fields(); void setFields(const AbstractMetaFieldList &fields); void addField(const AbstractMetaField &field); + bool hasStaticFields() const; std::optional<AbstractMetaField> findField(const QString &name) const; diff --git a/sources/shiboken6/generator/shiboken/cppgenerator.cpp b/sources/shiboken6/generator/shiboken/cppgenerator.cpp index 9eec438a6..2dd13c1c6 100644 --- a/sources/shiboken6/generator/shiboken/cppgenerator.cpp +++ b/sources/shiboken6/generator/shiboken/cppgenerator.cpp @@ -765,6 +765,9 @@ void CppGenerator::generateClass(TextStream &s, const GeneratorContext &classCon writeConverterFunctions(s, metaClass, classContext); writeClassRegister(s, metaClass, classContext, signatureStream); + if (metaClass->hasStaticFields()) + writeStaticFieldInitialization(s, metaClass); + // class inject-code native/end if (!metaClass->typeEntry()->codeSnips().isEmpty()) { writeClassCodeSnips(s, metaClass->typeEntry()->codeSnips(), @@ -5313,6 +5316,12 @@ QString CppGenerator::getInitFunctionName(const GeneratorContext &context) const : getFilteredCppSignatureString(context.preciseType().cppSignature()); } +QString CppGenerator::getSimpleClassStaticFieldsInitFunctionName(const AbstractMetaClass *metaClass) const +{ + return QLatin1String("init_") + getSimpleClassInitFunctionName(metaClass) + + QLatin1String("StaticFields"); +} + void CppGenerator::writeSignatureStrings(TextStream &s, const QString &signatures, const QString &arrayName, @@ -5503,19 +5512,6 @@ void CppGenerator::writeClassRegister(TextStream &s, if (metaClass->hasSignals()) writeSignalInitialization(s, metaClass); - // Write static fields - const AbstractMetaFieldList &fields = metaClass->fields(); - for (const AbstractMetaField &field : fields) { - if (!field.isStatic()) - continue; - s << "PyDict_SetItemString(reinterpret_cast<PyTypeObject *>(" - << cpythonTypeName(metaClass) << ")->tp_dict, \"" - << field.name() << "\", "; - writeToPythonConversion(s, field.type(), metaClass, field.qualifiedCppName()); - s << ");\n"; - } - s << '\n'; - // class inject-code target/end if (!classTypeEntry->codeSnips().isEmpty()) { s << '\n'; @@ -5546,6 +5542,23 @@ void CppGenerator::writeClassRegister(TextStream &s, s << outdent << "}\n"; } +void CppGenerator::writeStaticFieldInitialization(TextStream &s, + const AbstractMetaClass *metaClass) const +{ + s << "\nvoid " << getSimpleClassStaticFieldsInitFunctionName(metaClass) + << "()\n{\n" << indent << "auto dict = reinterpret_cast<PyTypeObject *>(" + << cpythonTypeName(metaClass) << ")->tp_dict;\n"; + for (const AbstractMetaField &field : metaClass->fields()) { + if (field.isStatic()) { + s << "PyDict_SetItemString(dict, \"" << field.name() + << "\",\n "; + writeToPythonConversion(s, field.type(), metaClass, field.qualifiedCppName()); + s << ");\n"; + } + } + s << '\n' << outdent << "}\n"; +} + void CppGenerator::writeInitQtMetaTypeFunctionBody(TextStream &s, const GeneratorContext &context) const { const AbstractMetaClass *metaClass = context.metaClass(); @@ -5937,11 +5950,17 @@ bool CppGenerator::finishGeneration() writeMethodDefinition(s_globalFunctionDef, overloads); } + AbstractMetaClassCList classesWithStaticFields; for (auto cls : api().classes()){ if (shouldGenerate(cls)) { writeInitFunc(s_classInitDecl, s_classPythonDefines, getSimpleClassInitFunctionName(cls), cls->typeEntry()->targetLangEnclosingEntry()); + if (cls->hasStaticFields()) { + s_classInitDecl << "void " + << getSimpleClassStaticFieldsInitFunctionName(cls) << "();\n"; + classesWithStaticFields.append(cls); + } } } @@ -6232,6 +6251,14 @@ bool CppGenerator::finishGeneration() s << "Shiboken::Module::registerTypes(module, " << cppApiVariableName() << ");\n"; s << "Shiboken::Module::registerTypeConverters(module, " << convertersVariableName() << ");\n"; + // Static fields are registered last since they may use converter functions + // of the previously registered types (PYSIDE-1529). + if (!classesWithStaticFields.isEmpty()) { + s << "\n// Static field initialization\n"; + for (auto cls : qAsConst(classesWithStaticFields)) + s << getSimpleClassStaticFieldsInitFunctionName(cls) << "();\n"; + } + s << "\nif (PyErr_Occurred()) {\n" << indent << "PyErr_Print();\n" << "Py_FatalError(\"can't initialize module " << moduleName() << "\");\n" diff --git a/sources/shiboken6/generator/shiboken/cppgenerator.h b/sources/shiboken6/generator/shiboken/cppgenerator.h index 97811c946..26958e6a4 100644 --- a/sources/shiboken6/generator/shiboken/cppgenerator.h +++ b/sources/shiboken6/generator/shiboken/cppgenerator.h @@ -278,6 +278,7 @@ private: QString getInitFunctionName(const GeneratorContext &context) const; QString getSimpleClassInitFunctionName(const AbstractMetaClass *metaClass) const; + QString getSimpleClassStaticFieldsInitFunctionName(const AbstractMetaClass *metaClass) const; void writeSignatureStrings(TextStream &s, const QString &signatures, const QString &arrayName, @@ -286,6 +287,8 @@ private: const AbstractMetaClass *metaClass, const GeneratorContext &classContext, const QString &signatures) const; + void writeStaticFieldInitialization(TextStream &s, + const AbstractMetaClass *metaClass) const; void writeClassDefinition(TextStream &s, const AbstractMetaClass *metaClass, const GeneratorContext &classContext); |