diff options
author | Friedemann Kleint <Friedemann.Kleint@qt.io> | 2018-12-13 14:03:32 +0100 |
---|---|---|
committer | Friedemann Kleint <Friedemann.Kleint@qt.io> | 2019-01-03 18:50:54 +0000 |
commit | e254c3c2aa140016e298107a0297885234abfde7 (patch) | |
tree | db15ce3a6329ec3cc87a1b53f91e62ce754aeadc /sources/shiboken2/libshiboken/basewrapper.cpp | |
parent | 0b352fca7391d01ce410ec0c04c285326e465dc1 (diff) |
Fix crash related to multiple inheritance
In the <class>_PTR_CppToPython_<class> converter function (written by
CppGenerator::writeConverterFunctions()), the generated code
used typeid(*ptr).name() to retrieve the name to use for the
SbkObjectTypes. This construct returns the name of the outermost
class (for example, "QWidget" for a QWidget-type paint device returned
by QPainter::device()), as opposed to "QPaintDevice *" returned by
typeid(ptr).name(). This caused a crash with multiple inheritance
since QWidget inherits QObject and QPaintDevice and the "QWidget"
type was associated with the QPaintDevice pointer.
To fix this:
- Add API to libshiboken to obtain the SbkObjectType* by name
and check for the presence of a special cast function (multiple
inheritance).
- Generate the code of <class>_PTR_CppToPython_<class> as follows:
Check whether the outermost type obtained by typeid(*ptr).name()
has a special cast function. If that is the case, use the
type name obtained by typeid(ptr).name() (base class) to create
the wrapper.
Change-Id: I8ee6b4c084e9dafa434623433661809b83aedee5
Fixes: PYSIDE-868
Reviewed-by: Cristian Maureira-Fredes <cristian.maureira-fredes@qt.io>
Diffstat (limited to 'sources/shiboken2/libshiboken/basewrapper.cpp')
-rw-r--r-- | sources/shiboken2/libshiboken/basewrapper.cpp | 28 |
1 files changed, 20 insertions, 8 deletions
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); } |