diff options
4 files changed, 46 insertions, 5 deletions
diff --git a/sources/shiboken6/ApiExtractor/typesystemparser.cpp b/sources/shiboken6/ApiExtractor/typesystemparser.cpp index 1c1565ac2..71e80cfa8 100644 --- a/sources/shiboken6/ApiExtractor/typesystemparser.cpp +++ b/sources/shiboken6/ApiExtractor/typesystemparser.cpp @@ -88,6 +88,7 @@ constexpr auto pyiTypeAttribute = "pyi-type"_L1; constexpr auto overloadNumberAttribute = "overload-number"_L1; constexpr auto ownershipAttribute = "owner"_L1; constexpr auto packageAttribute = "package"_L1; +constexpr auto polymorphicBaseAttribute = "polymorphic-base"_L1; constexpr auto positionAttribute = "position"_L1; constexpr auto preferredConversionAttribute = "preferred-conversion"_L1; constexpr auto preferredTargetLangTypeAttribute = "preferred-target-lang-type"_L1; @@ -1810,8 +1811,10 @@ void TypeSystemParser::applyComplexTypeAttributes(const ConditionalStreamReader ctype->setGenericClass(v); } else if (name == targetLangNameAttribute) { ctype->setTargetLangName(attributes->takeAt(i).value().toString()); - } else if (name == u"polymorphic-base") { - ctype->setPolymorphicIdValue(attributes->takeAt(i).value().toString()); + } else if (name == polymorphicBaseAttribute) { + const bool v = convertBoolean(attributes->takeAt(i).value(), + polymorphicBaseAttribute, false); + ctype->setIsPolymorphicBase(v); } else if (name == u"polymorphic-name-function") { ctype->setPolymorphicNameFunction(attributes->takeAt(i).value().toString()); } else if (name == u"polymorphic-id-expression") { diff --git a/sources/shiboken6/doc/typesystem_specifying_types.rst b/sources/shiboken6/doc/typesystem_specifying_types.rst index 7a1471b44..66e68ae2b 100644 --- a/sources/shiboken6/doc/typesystem_specifying_types.rst +++ b/sources/shiboken6/doc/typesystem_specifying_types.rst @@ -453,6 +453,7 @@ or other type nodes and may contain :ref:`add-function`, :ref:`add-pymethoddef`, parent-management="yes | no" polymorphic-id-expression="..." polymorphic-name-function="..." + polymorphic-base="yes | no" private="yes | no" qt-metaobject="yes | no" qt-register-metatype = "yes | no | base" @@ -540,6 +541,21 @@ expression checking whether a base class pointer is of the matching type. For example, in a ``virtual eventHandler(BaseEvent *e)`` function, this is used to construct a Python wrapper matching the derived class (for example, a ``MouseEvent`` or similar). +The attribute value may contain placeholders: + +%1 + Fully qualified class name + +%B + Fully qualified name of the base class (found by base class + search or as indicated by **polymorphic-base**). + +To check for a class inheriting ``BaseEvent``, specify: + +.. code-block:: xml + + <object-type name="MouseEvent" + polymorphic-id-expression="%B->type() == BaseEvent::MouseEvent"/> The *optional* **polymorphic-name-function** specifies the name of a function returning the type name of a derived class on the base class @@ -548,6 +564,10 @@ However, this fails if the type hierarchy does not have virtual functions. In this case, a function is required which typically decides depending on some type enumeration. +The *optional* **polymorphic-base** attribute indicates +whether the class is the base class of a class hierarchy +(used for the *%B* placeholder in **polymorphic-id-expression**). + interface-type ^^^^^^^^^^^^^^ diff --git a/sources/shiboken6/generator/shiboken/cppgenerator.cpp b/sources/shiboken6/generator/shiboken/cppgenerator.cpp index 26caef9c4..05afde69f 100644 --- a/sources/shiboken6/generator/shiboken/cppgenerator.cpp +++ b/sources/shiboken6/generator/shiboken/cppgenerator.cpp @@ -5720,6 +5720,24 @@ void CppGenerator::writeInitQtMetaTypeFunctionBody(TextStream &s, const Generato } } +void CppGenerator::replacePolymorphicIdPlaceHolders(const AbstractMetaClassCPtr &metaClass, + QString *id) +{ + if (id->contains("%1"_L1)) { + QString replacement = " reinterpret_cast< "_L1 + m_gsp + metaClass->qualifiedCppName() + + " *>(cptr)"_L1; + id->replace("%1"_L1, replacement); + } + if (id->contains("%B"_L1)) { + auto baseClass = metaClass; + while (!baseClass->typeEntry()->isPolymorphicBase() && baseClass->baseClass()) + baseClass = baseClass->baseClass(); + QString replacement = " reinterpret_cast< "_L1 + m_gsp + baseClass->qualifiedCppName() + + " *>(cptr)"_L1; + id->replace("%B"_L1, replacement); + } +} + void CppGenerator::writeTypeDiscoveryFunction(TextStream &s, const AbstractMetaClassCPtr &metaClass) { @@ -5731,9 +5749,7 @@ void CppGenerator::writeTypeDiscoveryFunction(TextStream &s, << sbkUnusedVariableCast("instanceType"); if (!polymorphicExpr.isEmpty()) { - polymorphicExpr.replace(u"%1"_s, " reinterpret_cast< "_L1 - + m_gsp + metaClass->qualifiedCppName() - + " *>(cptr)"_L1); + replacePolymorphicIdPlaceHolders(metaClass, &polymorphicExpr); s << " if (" << polymorphicExpr << ")\n" << indent << "return cptr;\n" << outdent; } else if (metaClass->isPolymorphic()) { diff --git a/sources/shiboken6/generator/shiboken/cppgenerator.h b/sources/shiboken6/generator/shiboken/cppgenerator.h index 94ad87bbe..7e87fd9f3 100644 --- a/sources/shiboken6/generator/shiboken/cppgenerator.h +++ b/sources/shiboken6/generator/shiboken/cppgenerator.h @@ -192,6 +192,8 @@ private: static void writeTypeCheck(TextStream& s, const std::shared_ptr<OverloadDataNode> &overloadData, const QString &argumentName); + static void replacePolymorphicIdPlaceHolders(const AbstractMetaClassCPtr &metaClass, + QString *id); static void writeTypeDiscoveryFunction(TextStream &s, const AbstractMetaClassCPtr &metaClass); |