diff options
Diffstat (limited to 'sources/shiboken2')
-rw-r--r-- | sources/shiboken2/generator/shiboken2/cppgenerator.cpp | 44 | ||||
-rw-r--r-- | sources/shiboken2/libshiboken/basewrapper.cpp | 28 | ||||
-rw-r--r-- | sources/shiboken2/libshiboken/basewrapper.h | 14 | ||||
-rw-r--r-- | sources/shiboken2/tests/otherbinding/typediscovery_test.py | 10 |
4 files changed, 80 insertions, 16 deletions
diff --git a/sources/shiboken2/generator/shiboken2/cppgenerator.cpp b/sources/shiboken2/generator/shiboken2/cppgenerator.cpp index e46e0b968..9df0d61c5 100644 --- a/sources/shiboken2/generator/shiboken2/cppgenerator.cpp +++ b/sources/shiboken2/generator/shiboken2/cppgenerator.cpp @@ -50,6 +50,30 @@ QHash<QString, QString> CppGenerator::m_sqFuncs = QHash<QString, QString>(); QHash<QString, QString> CppGenerator::m_mpFuncs = QHash<QString, QString>(); QString CppGenerator::m_currentErrorCode(QLatin1String("0")); +static const char typeNameFunc[] = R"CPP( +template <class T> +static const char *typeNameOf(const T &t) +{ + const char *typeName = typeid(t).name(); + auto size = std::strlen(typeName); +#if defined(Q_CC_MSVC) // MSVC: "class QPaintDevice * __ptr64" + if (auto lastStar = strchr(typeName, '*')) { + // MSVC: "class QPaintDevice * __ptr64" + while (*--lastStar == ' ') { + } + size = lastStar - typeName + 1; + } +#else // g++, Clang: "QPaintDevice *" -> "P12QPaintDevice" + if (size > 2 && typeName[0] == 'P' && std::isdigit(typeName[1])) + ++typeName; +#endif + char *result = new char[size + 1]; + result[size] = '\0'; + strncpy(result, typeName, size); + return result; +} +)CPP"; + // utility functions inline AbstractMetaType* getTypeWithoutContainer(AbstractMetaType* arg) { @@ -336,6 +360,8 @@ void CppGenerator::generateClass(QTextStream &s, GeneratorContext &classContext) s << inc.toString() << endl; s << endl; + s << "\n#include <cctype>\n#include <cstring>\n"; + if (metaClass->typeEntry()->typeFlags() & ComplexTypeEntry::Deprecated) s << "#Deprecated" << endl; @@ -351,7 +377,7 @@ void CppGenerator::generateClass(QTextStream &s, GeneratorContext &classContext) } } - s << endl; + s << endl << endl << typeNameFunc << endl; // Create string literal for smart pointer getter method. if (classContext.forSmartPointer()) { @@ -1226,9 +1252,19 @@ void CppGenerator::writeConverterFunctions(QTextStream &s, const AbstractMetaCla c << INDENT << "return pyOut;" << endl; } c << INDENT << '}' << endl; - c << INDENT << "const char* typeName = typeid(*((" << typeName << "*)cppIn)).name();" << endl; - c << INDENT << "return Shiboken::Object::newObject(" << cpythonType; - c << ", const_cast<void*>(cppIn), false, false, typeName);"; + c << INDENT << "bool changedTypeName = false;\n" + << INDENT << "auto tCppIn = reinterpret_cast<const " << typeName << " *>(cppIn);\n" + << INDENT << "const char *typeName = typeid(*tCppIn).name();\n" + << INDENT << "auto sbkType = Shiboken::ObjectType::typeForTypeName(typeName);\n" + << INDENT << "if (sbkType && Shiboken::ObjectType::hasSpecialCastFunction(sbkType)) {\n" + << INDENT << " typeName = typeNameOf(tCppIn);\n" + << INDENT << " changedTypeName = true;\n" + << INDENT << " }\n" + << INDENT << "PyObject *result = Shiboken::Object::newObject(" << cpythonType + << ", const_cast<void*>(cppIn), false, /* exactType */ changedTypeName, typeName);\n" + << INDENT << "if (changedTypeName)\n" + << INDENT << " delete [] typeName;\n" + << INDENT << "return result;"; } std::swap(targetTypeName, sourceTypeName); writeCppToPythonFunction(s, code, sourceTypeName, targetTypeName); diff --git a/sources/shiboken2/libshiboken/basewrapper.cpp b/sources/shiboken2/libshiboken/basewrapper.cpp index c9e3b9d1b..e820e749b 100644 --- a/sources/shiboken2/libshiboken/basewrapper.cpp +++ b/sources/shiboken2/libshiboken/basewrapper.cpp @@ -831,6 +831,23 @@ void setTypeUserData(SbkObjectType* type, void* userData, DeleteUserDataFunc d_f sotp->d_func = d_func; } +// Try to find the exact type of cptr. +SbkObjectType *typeForTypeName(const char *typeName) +{ + SbkObjectType *result{}; + if (typeName) { + if (PyTypeObject *pyType = Shiboken::Conversions::getPythonTypeObject(typeName)) + result = reinterpret_cast<SbkObjectType*>(pyType); + } + return result; +} + +bool hasSpecialCastFunction(SbkObjectType *sbkType) +{ + const SbkObjectTypePrivate *d = PepType_SOTP(sbkType); + return d != nullptr && d->mi_specialcast != nullptr; +} + } // namespace ObjectType @@ -1191,7 +1208,6 @@ SbkObject *findColocatedChild(SbkObject *wrapper, return 0; } - PyObject *newObject(SbkObjectType* instanceType, void* cptr, bool hasOwnership, @@ -1200,13 +1216,9 @@ PyObject *newObject(SbkObjectType* instanceType, { // Try to find the exact type of cptr. if (!isExactType) { - PyTypeObject* exactType = 0; - if (typeName) { - exactType = Shiboken::Conversions::getPythonTypeObject(typeName); - if (exactType) - instanceType = reinterpret_cast<SbkObjectType*>(exactType); - } - if (!exactType) + if (SbkObjectType *exactType = ObjectType::typeForTypeName(typeName)) + instanceType = exactType; + else instanceType = BindingManager::instance().resolveType(&cptr, instanceType); } diff --git a/sources/shiboken2/libshiboken/basewrapper.h b/sources/shiboken2/libshiboken/basewrapper.h index 65849d783..15682c600 100644 --- a/sources/shiboken2/libshiboken/basewrapper.h +++ b/sources/shiboken2/libshiboken/basewrapper.h @@ -238,6 +238,20 @@ LIBSHIBOKEN_API void setSubTypeInitHook(SbkObjectType* self, SubTypeInitH LIBSHIBOKEN_API void* getTypeUserData(SbkObjectType* self); LIBSHIBOKEN_API void setTypeUserData(SbkObjectType* self, void* userData, DeleteUserDataFunc d_func); +/** + * Return an instance of SbkObjectType for a C++ type name as determined by + * typeinfo().name(). + * \param typeName Type name + * \since 5.12 + */ +LIBSHIBOKEN_API SbkObjectType *typeForTypeName(const char *typeName); + +/** + * Returns whether SbkObjectType has a special cast function (multiple inheritance) + * \param sbkType Sbk type + * \since 5.12 + */ +LIBSHIBOKEN_API bool hasSpecialCastFunction(SbkObjectType *sbkType); } namespace Object { diff --git a/sources/shiboken2/tests/otherbinding/typediscovery_test.py b/sources/shiboken2/tests/otherbinding/typediscovery_test.py index 6816b158a..a9eb88d80 100644 --- a/sources/shiboken2/tests/otherbinding/typediscovery_test.py +++ b/sources/shiboken2/tests/otherbinding/typediscovery_test.py @@ -51,14 +51,16 @@ class TypeDiscoveryTest(unittest.TestCase): def testMultipleInheritance(self): obj = OtherMultipleDerived.createObject("Base1"); self.assertEqual(type(obj), Base1) + # PYSIDE-868: In case of multiple inheritance, a factory + # function will return the base class wrapper. obj = OtherMultipleDerived.createObject("MDerived1"); - self.assertEqual(type(obj), MDerived1) + self.assertEqual(type(obj), Base1) obj = OtherMultipleDerived.createObject("SonOfMDerived1"); - self.assertEqual(type(obj), SonOfMDerived1) + self.assertEqual(type(obj), Base1) obj = OtherMultipleDerived.createObject("MDerived3"); - self.assertEqual(type(obj), MDerived3) + self.assertEqual(type(obj), Base1) obj = OtherMultipleDerived.createObject("OtherMultipleDerived"); - self.assertEqual(type(obj), OtherMultipleDerived) + self.assertEqual(type(obj), Base1) if __name__ == '__main__': unittest.main() |