diff options
Diffstat (limited to 'sources/shiboken6/libshiboken/basewrapper.cpp')
-rw-r--r-- | sources/shiboken6/libshiboken/basewrapper.cpp | 322 |
1 files changed, 216 insertions, 106 deletions
diff --git a/sources/shiboken6/libshiboken/basewrapper.cpp b/sources/shiboken6/libshiboken/basewrapper.cpp index f1622c30b..35d46b1aa 100644 --- a/sources/shiboken6/libshiboken/basewrapper.cpp +++ b/sources/shiboken6/libshiboken/basewrapper.cpp @@ -5,9 +5,12 @@ #include "basewrapper_p.h" #include "bindingmanager.h" #include "helper.h" +#include "pep384ext.h" #include "sbkconverter.h" #include "sbkenum.h" +#include "sbkerrors.h" #include "sbkfeature_base.h" +#include "sbkmodule.h" #include "sbkstring.h" #include "sbkstaticstrings.h" #include "sbkstaticstrings_p.h" @@ -21,6 +24,7 @@ #include <algorithm> #include "threadstatesaver.h" #include "signature.h" +#include "signature_p.h" #include "voidptr.h" #include <iostream> @@ -53,7 +57,7 @@ void Sbk_object_dealloc(PyObject *self) // This was not needed before Python 3.8 (Python issue 35810) Py_DECREF(Py_TYPE(self)); } - Py_TYPE(self)->tp_free(self); + PepExt_TypeCallFree(self); } static void SbkObjectType_tp_dealloc(PyTypeObject *pyType); @@ -70,6 +74,7 @@ void setDestroyQApplication(DestroyQAppHook func) // PYSIDE-535: Use the C API in PyPy instead of `op->ob_dict`, directly LIBSHIBOKEN_API PyObject *SbkObject_GetDict_NoRef(PyObject *op) { + assert(Shiboken::Object::checkType(op)); #ifdef PYPY_VERSION Shiboken::GilState state; auto *ret = PyObject_GenericGetDict(op, nullptr); @@ -103,20 +108,18 @@ check_set_special_type_attr(PyTypeObject *type, PyObject *value, const char *nam // PYSIDE-1177: Add a setter to allow setting type doc. static int -type_set_doc(PyTypeObject *type, PyObject *value, void *context) +type_set_doc(PyTypeObject *type, PyObject *value, void * /* context */) { if (!check_set_special_type_attr(type, value, "__doc__")) return -1; PyType_Modified(type); - return PyDict_SetItem(type->tp_dict, Shiboken::PyMagicName::doc(), value); + Shiboken::AutoDecRef tpDict(PepType_GetDict(type)); + return PyDict_SetItem(tpDict.object(), Shiboken::PyMagicName::doc(), value); } // PYSIDE-908: The function PyType_Modified does not work in PySide, so we need to -// explicitly pass __doc__. For __signature__ it _did_ actually work, because -// it was not existing before. We add them both for clarity. +// explicitly pass __doc__. static PyGetSetDef SbkObjectType_tp_getset[] = { - {const_cast<char *>("__signature__"), reinterpret_cast<getter>(Sbk_TypeGet___signature__), - nullptr, nullptr, nullptr}, {const_cast<char *>("__doc__"), reinterpret_cast<getter>(Sbk_TypeGet___doc__), reinterpret_cast<setter>(type_set_doc), nullptr, nullptr}, {const_cast<char *>("__dict__"), reinterpret_cast<getter>(Sbk_TypeGet___dict__), @@ -124,31 +127,53 @@ static PyGetSetDef SbkObjectType_tp_getset[] = { {nullptr, nullptr, nullptr, nullptr, nullptr} // Sentinel }; -static PyType_Slot SbkObjectType_Type_slots[] = { - {Py_tp_dealloc, reinterpret_cast<void *>(SbkObjectType_tp_dealloc)}, - {Py_tp_getattro, reinterpret_cast<void *>(mangled_type_getattro)}, - {Py_tp_base, static_cast<void *>(&PyType_Type)}, - {Py_tp_alloc, reinterpret_cast<void *>(PyType_GenericAlloc)}, - {Py_tp_new, reinterpret_cast<void *>(SbkObjectType_tp_new)}, - {Py_tp_free, reinterpret_cast<void *>(PyObject_GC_Del)}, - {Py_tp_getset, reinterpret_cast<void *>(SbkObjectType_tp_getset)}, - {0, nullptr} -}; - -// PYSIDE-535: The tp_itemsize field is inherited and does not need to be set. -// In PyPy, it _must_ not be set, because it would have the meaning that a -// `__len__` field must be defined. Not doing so creates a hard-to-find crash. -static PyType_Spec SbkObjectType_Type_spec = { - "1:Shiboken.ObjectType", - 0, - 0, // sizeof(PyMemberDef), not for PyPy without a __len__ defined - Py_TPFLAGS_DEFAULT|Py_TPFLAGS_BASETYPE, - SbkObjectType_Type_slots, -}; +static PyTypeObject *createObjectTypeType() +{ + PyType_Slot SbkObjectType_Type_slots[] = { + {Py_tp_dealloc, reinterpret_cast<void *>(SbkObjectType_tp_dealloc)}, + {Py_tp_getattro, reinterpret_cast<void *>(mangled_type_getattro)}, + {Py_tp_base, static_cast<void *>(&PyType_Type)}, + {Py_tp_alloc, reinterpret_cast<void *>(PyType_GenericAlloc)}, + {Py_tp_new, reinterpret_cast<void *>(SbkObjectType_tp_new)}, + {Py_tp_free, reinterpret_cast<void *>(PyObject_GC_Del)}, + {Py_tp_getset, reinterpret_cast<void *>(SbkObjectType_tp_getset)}, + {0, nullptr} + }; + + // PYSIDE-535: The tp_itemsize field is inherited and does not need to be set. + // In PyPy, it _must_ not be set, because it would have the meanin + // that a `__len__` field must be defined. Not doing so creates + // a hard-to-find crash. + // + // PYSIDE-2230: In Python < 3.12, the decision which base class should create + // the instance is arbitrarily drawn by the size of the type. + // Ignoring this creates a bug in the new version of bug_825 that + // selects the wrong metatype. + // + PyType_Spec SbkObjectType_Type_spec = { + "1:Shiboken.ObjectType", + static_cast<int>(PyType_Type.tp_basicsize) + 1, // see above + 0, // sizeof(PyMemberDef), not for PyPy without a __len__ defined + Py_TPFLAGS_DEFAULT|Py_TPFLAGS_BASETYPE|Py_TPFLAGS_TYPE_SUBCLASS, + SbkObjectType_Type_slots, + }; + + PyType_Spec SbkObjectType_Type_spec_312 = { + "1:Shiboken.ObjectType", + -long(sizeof(SbkObjectTypePrivate)), + 0, // sizeof(PyMemberDef), not for PyPy without a __len__ defined + Py_TPFLAGS_DEFAULT|Py_TPFLAGS_BASETYPE|Py_TPFLAGS_TYPE_SUBCLASS, + SbkObjectType_Type_slots, + }; + + return SbkType_FromSpec(_PepRuntimeVersion() >= 0x030C00 ? + &SbkObjectType_Type_spec_312 : + &SbkObjectType_Type_spec); +} PyTypeObject *SbkObjectType_TypeF(void) { - static auto *type = SbkType_FromSpec(&SbkObjectType_Type_spec); + static auto *type = createObjectTypeType(); return type; } @@ -185,10 +210,8 @@ static int SbkObject_tp_traverse(PyObject *self, visitproc visit, void *arg) if (sbkSelf->ob_dict) Py_VISIT(sbkSelf->ob_dict); -#if PY_VERSION_HEX >= 0x03090000 // This was not needed before Python 3.9 (Python issue 35810 and 40217) Py_VISIT(Py_TYPE(self)); -#endif return 0; } @@ -208,40 +231,55 @@ static int SbkObject_tp_clear(PyObject *self) return 0; } -static PyType_Slot SbkObject_Type_slots[] = { - {Py_tp_getattro, reinterpret_cast<void *>(SbkObject_GenericGetAttr)}, - {Py_tp_setattro, reinterpret_cast<void *>(SbkObject_GenericSetAttr)}, - {Py_tp_dealloc, reinterpret_cast<void *>(SbkDeallocWrapperWithPrivateDtor)}, - {Py_tp_traverse, reinterpret_cast<void *>(SbkObject_tp_traverse)}, - {Py_tp_clear, reinterpret_cast<void *>(SbkObject_tp_clear)}, - // unsupported: {Py_tp_weaklistoffset, (void *)offsetof(SbkObject, weakreflist)}, - {Py_tp_getset, reinterpret_cast<void *>(SbkObject_tp_getset)}, - // unsupported: {Py_tp_dictoffset, (void *)offsetof(SbkObject, ob_dict)}, - {0, nullptr} -}; -static PyType_Spec SbkObject_Type_spec = { - "1:Shiboken.Object", - sizeof(SbkObject), - 0, - Py_TPFLAGS_DEFAULT|Py_TPFLAGS_BASETYPE|Py_TPFLAGS_HAVE_GC, - SbkObject_Type_slots, -}; - -static const char *SbkObject_SignatureStrings[] = { - "Shiboken.Object(self)", - nullptr}; // Sentinel +static PyTypeObject *createObjectType() +{ + PyType_Slot SbkObject_Type_slots[] = { + {Py_tp_getattro, reinterpret_cast<void *>(SbkObject_GenericGetAttr)}, + {Py_tp_setattro, reinterpret_cast<void *>(SbkObject_GenericSetAttr)}, + {Py_tp_dealloc, reinterpret_cast<void *>(SbkDeallocWrapperWithPrivateDtor)}, + {Py_tp_traverse, reinterpret_cast<void *>(SbkObject_tp_traverse)}, + {Py_tp_clear, reinterpret_cast<void *>(SbkObject_tp_clear)}, + // unsupported: {Py_tp_weaklistoffset, (void *)offsetof(SbkObject, weakreflist)}, + {Py_tp_getset, reinterpret_cast<void *>(SbkObject_tp_getset)}, + // unsupported: {Py_tp_dictoffset, (void *)offsetof(SbkObject, ob_dict)}, + {0, nullptr} + }; + + PyType_Spec SbkObject_Type_spec = { + "1:Shiboken.Object", + sizeof(SbkObject), + 0, + Py_TPFLAGS_DEFAULT|Py_TPFLAGS_BASETYPE|Py_TPFLAGS_HAVE_GC, + SbkObject_Type_slots, + }; + + // PYSIDE-2230: When creating this type, we cannot easily handle the metaclass. + // In versions < Python 3.12, the metaclass can only be set + // indirectly by a base which has that metaclass. + // But before 3.12 is the minimum version, we cannot use the new + // function, although we would need this for 3.12 :-D + // We do a special patching here that is triggered through Py_None. + auto *type = SbkType_FromSpec_BMDWB(&SbkObject_Type_spec, + Py_None, // bases, spectial flag! + SbkObjectType_TypeF(), + offsetof(SbkObject, ob_dict), + offsetof(SbkObject, weakreflist), + nullptr); // bufferprocs + // Initialize the hidden data area. + _PepPostInit_SbkObject_Type(type); + return type; +} PyTypeObject *SbkObject_TypeF(void) { - static auto *type = SbkType_FromSpec_BMDWB(&SbkObject_Type_spec, - nullptr, // bases - SbkObjectType_TypeF(), - offsetof(SbkObject, ob_dict), - offsetof(SbkObject, weakreflist), - nullptr); // bufferprocs + static auto *type = createObjectType(); // bufferprocs return type; } +static const char *SbkObject_SignatureStrings[] = { + "Shiboken.Object(self)", + nullptr}; // Sentinel + static int mainThreadDeletionHandler(void *) { if (Py_IsInitialized()) @@ -353,6 +391,17 @@ static void SbkDeallocWrapperCommon(PyObject *pyObj, bool canDelete) } } +static inline PyObject *_Sbk_NewVarObject(PyTypeObject *type) +{ + // PYSIDE-1970: Support __slots__, implemented by PyVarObject + auto const baseSize = sizeof(SbkObject); + auto varCount = Py_SIZE(type); + auto *self = PyObject_GC_NewVar(PyObject, type, varCount); + if (varCount) + std::memset(reinterpret_cast<char *>(self) + baseSize, 0, varCount * sizeof(void *)); + return self; +} + void SbkDeallocWrapper(PyObject *pyObj) { SbkDeallocWrapperCommon(pyObj, true); @@ -376,7 +425,7 @@ void SbkObjectType_tp_dealloc(PyTypeObject *sbkType) auto pyObj = reinterpret_cast<PyObject *>(sbkType); PyObject_GC_UnTrack(pyObj); -#ifndef Py_LIMITED_API +#if !defined(Py_LIMITED_API) && !defined(PYPY_VERSION) # if PY_VERSION_HEX >= 0x030A0000 Py_TRASHCAN_BEGIN(pyObj, 1); # else @@ -394,7 +443,7 @@ void SbkObjectType_tp_dealloc(PyTypeObject *sbkType) Shiboken::Conversions::deleteConverter(sotp->converter); PepType_SOTP_delete(sbkType); } -#ifndef Py_LIMITED_API +#if !defined(Py_LIMITED_API) && !defined(PYPY_VERSION) # if PY_VERSION_HEX >= 0x030A0000 Py_TRASHCAN_END; # else @@ -432,7 +481,7 @@ PyObject *MakeQAppWrapper(PyTypeObject *type) } // monitoring the last application state - PyObject *qApp_curr = type != nullptr ? PyObject_GC_New(PyObject, type) : Py_None; + PyObject *qApp_curr = type != nullptr ? _Sbk_NewVarObject(type) : Py_None; static PyObject *builtins = PyEval_GetBuiltins(); if (PyDict_SetItem(builtins, Shiboken::PyName::qApp(), qApp_curr) < 0) return nullptr; @@ -465,7 +514,7 @@ static PyTypeObject *SbkObjectType_tp_new(PyTypeObject *metatype, PyObject *args PyObject *dict; static const char *kwlist[] = { "name", "bases", "dict", nullptr}; - if (!PyArg_ParseTupleAndKeywords(args, kwds, "sO!O!:sbktype", const_cast<char **>(kwlist), + if (!PyArg_ParseTupleAndKeywords(args, kwds, "OO!O!:sbktype", const_cast<char **>(kwlist), &name, &PyTuple_Type, &pyBases, &PyDict_Type, &dict)) @@ -473,22 +522,26 @@ static PyTypeObject *SbkObjectType_tp_new(PyTypeObject *metatype, PyObject *args for (int i=0, i_max=PyTuple_GET_SIZE(pyBases); i < i_max; i++) { PyObject *baseType = PyTuple_GET_ITEM(pyBases, i); - if (reinterpret_cast<PyTypeObject *>(baseType)->tp_new == SbkDummyNew) { + if (PepExt_Type_GetNewSlot(reinterpret_cast<PyTypeObject *>(baseType)) == SbkDummyNew) { // PYSIDE-595: A base class does not allow inheritance. return reinterpret_cast<PyTypeObject *>(SbkDummyNew(metatype, args, kwds)); } } - // PYSIDE-939: This is a temporary patch that circumvents the problem - // with Py_TPFLAGS_METHOD_DESCRIPTOR until this is finally solved. - // PyType_Ready uses mro(). We need to temporarily remove the flag from it's type. - // We cannot use PyMethodDescr_Type since it is not exported by Python 2.7 . - static PyTypeObject *PyMethodDescr_TypePtr = Py_TYPE( - PyObject_GetAttr(reinterpret_cast<PyObject *>(&PyType_Type), Shiboken::PyName::mro())); - auto hold = PyMethodDescr_TypePtr->tp_flags; - PyMethodDescr_TypePtr->tp_flags &= ~Py_TPFLAGS_METHOD_DESCRIPTOR; - auto *newType = PepType_Type_tp_new(metatype, args, kwds); - PyMethodDescr_TypePtr->tp_flags = hold; + // PYSIDE-939: This is still a temporary patch that circumvents the problem + // with Py_TPFLAGS_METHOD_DESCRIPTOR. The problem exists in Python 3.8 + // until 3.9.12, only. We check the runtime and hope for this version valishing. + // https://github.com/python/cpython/issues/92112 will not be fixed for 3.8 :/ + PyTypeObject *newType{}; + static auto triplet = _PepRuntimeVersion(); + if (triplet >= (3 << 16 | 8 << 8 | 0) && triplet < (3 << 16 | 9 << 8 | 13)) { + auto hold = PyMethodDescr_Type.tp_flags; + PyMethodDescr_Type.tp_flags &= ~Py_TPFLAGS_METHOD_DESCRIPTOR; + newType = PepType_Type_tp_new(metatype, args, kwds); + PyMethodDescr_Type.tp_flags = hold; + } else { + newType = PepType_Type_tp_new(metatype, args, kwds); + } if (!newType) return nullptr; @@ -537,11 +590,11 @@ static PyTypeObject *SbkObjectType_tp_new(PyTypeObject *metatype, PyObject *args return newType; } -static PyObject *_setupNew(SbkObject *self, PyTypeObject *subtype) +static PyObject *_setupNew(PyObject *obSelf, PyTypeObject *subtype) { auto *obSubtype = reinterpret_cast<PyObject *>(subtype); auto *sbkSubtype = subtype; - auto *obSelf = reinterpret_cast<PyObject *>(self); + auto *self = reinterpret_cast<SbkObject *>(obSelf); Py_INCREF(obSubtype); auto d = new SbkObjectPrivate; @@ -565,18 +618,19 @@ static PyObject *_setupNew(SbkObject *self, PyTypeObject *subtype) return obSelf; } -PyObject *SbkObject_tp_new(PyTypeObject *subtype, PyObject *, PyObject *) +PyObject *SbkObject_tp_new(PyTypeObject *subtype, PyObject * /* args */, PyObject * /* kwds */) { - SbkObject *self = PyObject_GC_New(SbkObject, subtype); + PyObject *self = _Sbk_NewVarObject(subtype); return _setupNew(self, subtype); } PyObject *SbkQApp_tp_new(PyTypeObject *subtype, PyObject *, PyObject *) { - auto self = reinterpret_cast<SbkObject *>(MakeQAppWrapper(subtype)); + auto *obSelf = MakeQAppWrapper(subtype); + auto *self = reinterpret_cast<SbkObject *>(obSelf); if (self == nullptr) return nullptr; - auto ret = _setupNew(self, subtype); + auto ret = _setupNew(obSelf, subtype); auto priv = self->d; priv->isQAppSingleton = 1; return ret; @@ -585,9 +639,9 @@ PyObject *SbkQApp_tp_new(PyTypeObject *subtype, PyObject *, PyObject *) PyObject *SbkDummyNew(PyTypeObject *type, PyObject *, PyObject *) { // PYSIDE-595: Give the same error as type_call does when tp_new is NULL. + const char regret[] = "¯\\_(ツ)_/¯"; PyErr_Format(PyExc_TypeError, - "cannot create '%.100s' instances ¯\\_(ツ)_/¯", - type->tp_name); + "cannot create '%.100s' instances %s", type->tp_name, regret); return nullptr; } @@ -618,6 +672,12 @@ PyObject *FallbackRichCompare(PyObject *self, PyObject *other, int op) return res; } +bool SbkObjectType_Check(PyTypeObject *type) +{ + static auto *meta = SbkObjectType_TypeF(); + return Py_TYPE(type) == meta || PyType_IsSubtype(Py_TYPE(type), meta); +} + } //extern "C" @@ -705,9 +765,6 @@ void init() //Init private data Pep384_Init(); - if (PyType_Ready(SbkEnumType_TypeF()) < 0) - Py_FatalError("[libshiboken] Failed to initialize Shiboken.SbkEnumType metatype."); - if (PyType_Ready(SbkObjectType_TypeF()) < 0) Py_FatalError("[libshiboken] Failed to initialize Shiboken.BaseWrapperType metatype."); @@ -720,14 +777,20 @@ void init() } // PYSIDE-1415: Publish Shiboken objects. -void initSignature(PyObject *module) +// PYSIDE-1735: Initialize the whole Shiboken startup. +void initShibokenSupport(PyObject *module) { - auto *type = SbkObject_TypeF(); - if (InitSignatureStrings(type, SbkObject_SignatureStrings) < 0) - return; - Py_INCREF(SbkObject_TypeF()); PyModule_AddObject(module, "Object", reinterpret_cast<PyObject *>(SbkObject_TypeF())); + + // PYSIDE-1735: When the initialization was moved into Shiboken import, this + // Py_INCREF became necessary. No idea why. + Py_INCREF(module); + init_shibokensupport_module(); + + auto *type = SbkObject_TypeF(); + if (InitSignatureStrings(type, SbkObject_SignatureStrings) < 0) + Py_FatalError("Error in initShibokenSupport"); } // setErrorAboutWrongArguments now gets overload info from the signature module. @@ -737,6 +800,32 @@ void setErrorAboutWrongArguments(PyObject *args, const char *funcName, PyObject SetError_Argument(args, funcName, info); } +PyObject *returnWrongArguments(PyObject *args, const char *funcName, PyObject *info) +{ + setErrorAboutWrongArguments(args, funcName, info); + return {}; +} + +int returnWrongArguments_Zero(PyObject *args, const char *funcName, PyObject *info) +{ + setErrorAboutWrongArguments(args, funcName, info); + return 0; +} + +int returnWrongArguments_MinusOne(PyObject *args, const char *funcName, PyObject *info) +{ + setErrorAboutWrongArguments(args, funcName, info); + return -1; +} + +PyObject *returnFromRichCompare(PyObject *result) +{ + if (result && !PyErr_Occurred()) + return result; + Shiboken::Errors::setOperatorNotImplemented(); + return {}; +} + PyObject *checkInvalidArgumentCount(Py_ssize_t numArgs, Py_ssize_t minArgs, Py_ssize_t maxArgs) { PyObject *result = nullptr; @@ -899,13 +988,23 @@ introduceWrapperType(PyObject *enclosingObject, auto sotp = PepType_SOTP(type); if (wrapperFlags & DeleteInMainThread) sotp->delete_in_main_thread = 1; + sotp->type_behaviour = (wrapperFlags & Value) != 0 + ? BEHAVIOUR_VALUETYPE : BEHAVIOUR_OBJECTTYPE; setOriginalName(type, originalName); setDestructorFunction(type, cppObjDtor); auto *ob_type = reinterpret_cast<PyObject *>(type); - if (wrapperFlags & InnerClass) + if (wrapperFlags & InnerClass) { + // PYSIDE-2230: Instead of tp_dict, use the enclosing type. + // This stays interface compatible. + if (PyType_Check(enclosingObject)) { + AutoDecRef tpDict(PepType_GetDict(reinterpret_cast<PyTypeObject *>(enclosingObject))); + return PyDict_SetItemString(tpDict, typeName, ob_type) == 0 ? type : nullptr; + } + assert(PyDict_Check(enclosingObject)); return PyDict_SetItemString(enclosingObject, typeName, ob_type) == 0 ? type : nullptr; + } // PyModule_AddObject steals type's reference. Py_INCREF(ob_type); @@ -920,16 +1019,19 @@ introduceWrapperType(PyObject *enclosingObject, void setSubTypeInitHook(PyTypeObject *type, SubTypeInitHook func) { + assert(SbkObjectType_Check(type)); PepType_SOTP(type)->subtype_init = func; } void *getTypeUserData(PyTypeObject *type) { + assert(SbkObjectType_Check(type)); return PepType_SOTP(type)->user_data; } void setTypeUserData(PyTypeObject *type, void *userData, DeleteUserDataFunc d_func) { + assert(SbkObjectType_Check(type)); auto *sotp = PepType_SOTP(type); sotp->user_data = userData; sotp->d_func = d_func; @@ -1191,11 +1293,10 @@ void makeValid(SbkObject *self) // If has ref to other objects make all valid again if (self->d->referredObjects) { - RefCountMap &refCountMap = *(self->d->referredObjects); - RefCountMap::iterator iter; - for (auto it = refCountMap.begin(), end = refCountMap.end(); it != end; ++it) { - if (Shiboken::Object::checkType(it->second)) - makeValid(reinterpret_cast<SbkObject *>(it->second)); + const RefCountMap &refCountMap = *(self->d->referredObjects); + for (const auto &p : refCountMap) { + if (Shiboken::Object::checkType(p.second)) + makeValid(reinterpret_cast<SbkObject *>(p.second)); } } } @@ -1231,7 +1332,8 @@ bool setCppPointer(SbkObject *sbkObj, PyTypeObject *desiredType, void *cptr) const bool alreadyInitialized = sbkObj->d->cptr[idx] != nullptr; if (alreadyInitialized) - PyErr_SetString(PyExc_RuntimeError, "You can't initialize an object twice!"); + PyErr_Format(PyExc_RuntimeError, "You can't initialize an %s object in class %s twice!", + desiredType->tp_name, type->tp_name); else sbkObj->d->cptr[idx] = cptr; @@ -1545,7 +1647,7 @@ void deallocData(SbkObject *self, bool cleanup) } delete self->d; // PYSIDE-205: always delete d. Py_XDECREF(self->ob_dict); - Py_TYPE(self)->tp_free(self); + PepExt_TypeCallFree(reinterpret_cast<PyObject *>(self)); } void setTypeUserData(SbkObject *wrapper, void *userData, DeleteUserDataFunc d_func) @@ -1637,6 +1739,11 @@ static std::vector<PyTypeObject *> getBases(SbkObject *self) : std::vector<PyTypeObject *>(1, Py_TYPE(self)); } +static bool isValueType(SbkObject *self) +{ + return PepType_SOTP(Py_TYPE(self))->type_behaviour == BEHAVIOUR_VALUETYPE; +} + void _debugFormat(std::ostream &s, SbkObject *self) { assert(self); @@ -1660,6 +1767,8 @@ void _debugFormat(std::ostream &s, SbkObject *self) s << " [validCppObject]"; if (d->cppObjectCreated) s << " [wasCreatedByPython]"; + s << (isValueType(self) ? " [value]" : " [object]"); + if (d->parentInfo) { if (auto *parent = d->parentInfo->parent) s << ", parent=" << reinterpret_cast<PyObject *>(parent)->ob_type->tp_name @@ -1690,8 +1799,9 @@ std::string info(SbkObject *self) s << "hasOwnership...... " << bool(self->d->hasOwnership) << "\n" "containsCppWrapper " << self->d->containsCppWrapper << "\n" "validCppObject.... " << self->d->validCppObject << "\n" - "wasCreatedByPython " << self->d->cppObjectCreated << "\n"; - + "wasCreatedByPython " << self->d->cppObjectCreated << "\n" + "value...... " << isValueType(self) << "\n" + "reference count... " << reinterpret_cast<PyObject *>(self)->ob_refcnt << '\n'; if (self->d->parentInfo && self->d->parentInfo->parent) { s << "parent............ "; @@ -1709,17 +1819,17 @@ std::string info(SbkObject *self) } if (self->d->referredObjects && !self->d->referredObjects->empty()) { - Shiboken::RefCountMap &map = *self->d->referredObjects; + const Shiboken::RefCountMap &map = *self->d->referredObjects; s << "referred objects.. "; std::string lastKey; - for (auto it = map.begin(), end = map.end(); it != end; ++it) { - if (it->first != lastKey) { + for (const auto &p : map) { + if (p.first != lastKey) { if (!lastKey.empty()) s << " "; - s << '"' << it->first << "\" => "; - lastKey = it->first; + s << '"' << p.first << "\" => "; + lastKey = p.first; } - Shiboken::AutoDecRef obj(PyObject_Str(it->second)); + Shiboken::AutoDecRef obj(PyObject_Str(p.second)); s << String::toCString(obj) << ' '; } s << '\n'; |