diff options
author | Friedemann Kleint <Friedemann.Kleint@qt.io> | 2024-01-12 12:11:20 +0100 |
---|---|---|
committer | Friedemann Kleint <Friedemann.Kleint@qt.io> | 2024-01-16 11:20:58 +0100 |
commit | 15fe017be6eb8b3aaf32d06eb21c61bd7eb3907e (patch) | |
tree | 7208cfd73e38ce3cc78e67eb88fa3d301719c79d | |
parent | a136723223b06169321296cd6cbc4c4c694e5153 (diff) |
Use PyType_GetSlot() instead of accessing PyTypeObject's slots in library code
Using PepType_GetSlot() as is requires adding ugly casts. To work
around, add a new file with convenience helper functions in C++
linkage. This also allows for using templates for tp_alloc.
Task-number: PYSIDE-560
Change-Id: Ia50a226f5b545861f885d600445b91b4e11713c5
Reviewed-by: Christian Tismer <tismer@stackless.com>
-rw-r--r-- | sources/pyside6/PySide6/QtQml/pysideqmlvolatilebool.cpp | 4 | ||||
-rw-r--r-- | sources/pyside6/libpyside/class_property.cpp | 11 | ||||
-rw-r--r-- | sources/pyside6/libpyside/dynamicqmetaobject.cpp | 2 | ||||
-rw-r--r-- | sources/pyside6/libpyside/globalreceiverv2.cpp | 3 | ||||
-rw-r--r-- | sources/pyside6/libpyside/pysideclassdecorator_p.h | 5 | ||||
-rw-r--r-- | sources/pyside6/libpyside/pysideproperty.cpp | 5 | ||||
-rw-r--r-- | sources/pyside6/libpyside/pysidesignal.cpp | 17 | ||||
-rw-r--r-- | sources/pyside6/libpysideqml/pysideqmllistproperty.cpp | 3 | ||||
-rw-r--r-- | sources/shiboken6/libshiboken/CMakeLists.txt | 1 | ||||
-rw-r--r-- | sources/shiboken6/libshiboken/basewrapper.cpp | 7 | ||||
-rw-r--r-- | sources/shiboken6/libshiboken/pep384ext.h | 89 | ||||
-rw-r--r-- | sources/shiboken6/libshiboken/sbkcontainer.h | 7 | ||||
-rw-r--r-- | sources/shiboken6/libshiboken/sbkfeature_base.cpp | 3 | ||||
-rw-r--r-- | sources/shiboken6/libshiboken/voidptr.cpp | 4 |
14 files changed, 130 insertions, 31 deletions
diff --git a/sources/pyside6/PySide6/QtQml/pysideqmlvolatilebool.cpp b/sources/pyside6/PySide6/QtQml/pysideqmlvolatilebool.cpp index e92e13aaf..6e403ab72 100644 --- a/sources/pyside6/PySide6/QtQml/pysideqmlvolatilebool.cpp +++ b/sources/pyside6/PySide6/QtQml/pysideqmlvolatilebool.cpp @@ -3,6 +3,7 @@ #include "pysideqmlvolatilebool.h" +#include <pep384ext.h> #include <signature.h> #include <QtCore/QDebug> @@ -30,8 +31,7 @@ QtQml_VolatileBoolObject_new(PyTypeObject *type, PyObject *args, PyObject *kwds) if (ok < 0) return nullptr; - QtQml_VolatileBoolObject *self - = reinterpret_cast<QtQml_VolatileBoolObject *>(type->tp_alloc(type, 0)); + auto *self = PepExt_TypeCallAlloc<QtQml_VolatileBoolObject>(type, 0); if (self != nullptr) self->flag = new AtomicBool(ok); diff --git a/sources/pyside6/libpyside/class_property.cpp b/sources/pyside6/libpyside/class_property.cpp index 99104445c..2bed97ef5 100644 --- a/sources/pyside6/libpyside/class_property.cpp +++ b/sources/pyside6/libpyside/class_property.cpp @@ -5,6 +5,7 @@ #include "pysidestaticstrings.h" #include "feature_select.h" +#include <pep384ext.h> #include <shiboken.h> #include <sbkstaticstrings.h> @@ -23,14 +24,14 @@ extern "C" { // `class_property.__get__()`: Always pass the class instead of the instance. static PyObject *PyClassProperty_descr_get(PyObject *self, PyObject * /*ob*/, PyObject *cls) { - return PyProperty_Type.tp_descr_get(self, cls, cls); + return PepExt_Type_GetDescrGetSlot(&PyProperty_Type)(self, cls, cls); } // `class_property.__set__()`: Just like the above `__get__()`. static int PyClassProperty_descr_set(PyObject *self, PyObject *obj, PyObject *value) { PyObject *cls = PyType_Check(obj) ? obj : reinterpret_cast<PyObject *>(Py_TYPE(obj)); - return PyProperty_Type.tp_descr_set(self, cls, value); + return PepExt_Type_GetDescrSetSlot(&PyProperty_Type)(self, cls, value); } // PYSIDE-2230: Why is this metaclass necessary? @@ -80,7 +81,7 @@ static int PyClassProperty_tp_init(PyObject *self, PyObject *args, PyObject *kwa { auto hold = Py_TYPE(self); self->ob_type = &PyProperty_Type; - auto ret = PyProperty_Type.tp_init(self, args, kwargs); + auto ret = PepExt_Type_GetInitSlot(&PyProperty_Type)(self, args, kwargs); self->ob_type = hold; return ret; } @@ -138,9 +139,9 @@ static int SbkObjectType_meta_setattro(PyObject *obj, PyObject *name, PyObject * && !PyObject_IsInstance(value, class_prop); if (call_descr_set) { // Call `class_property.__set__()` instead of replacing the `class_property`. - return Py_TYPE(descr)->tp_descr_set(descr, obj, value); + return PepExt_Type_GetDescrSetSlot(Py_TYPE(descr))(descr, obj, value); } // Replace existing attribute. - return PyType_Type.tp_setattro(obj, name, value); + return PepExt_Type_GetSetAttroSlot(&PyType_Type)(obj, name, value); } } // extern "C" diff --git a/sources/pyside6/libpyside/dynamicqmetaobject.cpp b/sources/pyside6/libpyside/dynamicqmetaobject.cpp index b41dbc275..048001f81 100644 --- a/sources/pyside6/libpyside/dynamicqmetaobject.cpp +++ b/sources/pyside6/libpyside/dynamicqmetaobject.cpp @@ -634,7 +634,7 @@ void MetaObjectBuilderPrivate::parsePythonType(PyTypeObject *type) const int index = m_baseObject->indexOfProperty(name); if (index == -1) addProperty(name, value); - } else if (Py_TYPE(value)->tp_call != nullptr) { + } else if (PepType_GetSlot(Py_TYPE(value), Py_tp_call) != nullptr) { // PYSIDE-198: PyFunction_Check does not work with Nuitka. // Register slots. if (PyObject_HasAttr(value, slotAttrName)) { diff --git a/sources/pyside6/libpyside/globalreceiverv2.cpp b/sources/pyside6/libpyside/globalreceiverv2.cpp index 09385645d..5fcf224ea 100644 --- a/sources/pyside6/libpyside/globalreceiverv2.cpp +++ b/sources/pyside6/libpyside/globalreceiverv2.cpp @@ -9,6 +9,7 @@ #include <autodecref.h> #include <gilstate.h> +#include <pep384ext.h> #include <QtCore/QMetaMethod> #include <QtCore/QSet> @@ -135,7 +136,7 @@ PyObject *DynamicSlotDataV2::callback() //create a callback based on method data if (m_isMethod) - callback = Py_TYPE(m_callback)->tp_descr_get(m_callback, m_pythonSelf, nullptr); + callback = PepExt_Type_CallDescrGet(m_callback, m_pythonSelf, nullptr); else Py_INCREF(callback); diff --git a/sources/pyside6/libpyside/pysideclassdecorator_p.h b/sources/pyside6/libpyside/pysideclassdecorator_p.h index d4e21a5b4..6068f6a2e 100644 --- a/sources/pyside6/libpyside/pysideclassdecorator_p.h +++ b/sources/pyside6/libpyside/pysideclassdecorator_p.h @@ -7,6 +7,7 @@ #include <pysidemacros.h> #include <sbkpython.h> +#include <pep384ext.h> #include <QtCore/QByteArray> @@ -119,7 +120,7 @@ struct Methods { static PyObject *tp_new(PyTypeObject *subtype) { - auto *result = reinterpret_cast<PySideClassDecorator *>(subtype->tp_alloc(subtype, 0)); + auto *result = PepExt_TypeCallAlloc<PySideClassDecorator>(subtype, 0); result->d = new DecoratorPrivate; return reinterpret_cast<PyObject *>(result); } @@ -129,7 +130,7 @@ struct Methods auto pySelf = reinterpret_cast<PyObject *>(self); auto decorator = reinterpret_cast<PySideClassDecorator *>(self); delete decorator->d; - Py_TYPE(pySelf)->tp_base->tp_free(self); + PepExt_TypeCallFree(Py_TYPE(pySelf)->tp_base, self); } static PyObject *tp_call(PyObject *self, PyObject *args, PyObject *kwds) diff --git a/sources/pyside6/libpyside/pysideproperty.cpp b/sources/pyside6/libpyside/pysideproperty.cpp index 2648ca43c..457415479 100644 --- a/sources/pyside6/libpyside/pysideproperty.cpp +++ b/sources/pyside6/libpyside/pysideproperty.cpp @@ -8,6 +8,7 @@ #include "pysidesignal_p.h" #include <shiboken.h> +#include <pep384ext.h> #include <signature.h> using namespace Shiboken; @@ -179,7 +180,7 @@ void PySidePropertyPrivate::metaCall(PyObject *source, QMetaObject::Call call, v static PyObject *qpropertyTpNew(PyTypeObject *subtype, PyObject * /* args */, PyObject * /* kwds */) { - auto *me = reinterpret_cast<PySideProperty *>(subtype->tp_alloc(subtype, 0)); + auto *me = PepExt_TypeCallAlloc<PySideProperty>(subtype, 0); me->d = new PySidePropertyPrivate; return reinterpret_cast<PyObject *>(me); } @@ -258,7 +259,7 @@ static void qpropertyDeAlloc(PyObject *self) Py_DECREF(Py_TYPE(self)); } PyObject_GC_UnTrack(self); - Py_TYPE(self)->tp_free(self); + PepExt_TypeCallFree(self); } // Create a copy of the property to prevent the @property.setter from modifying diff --git a/sources/pyside6/libpyside/pysidesignal.cpp b/sources/pyside6/libpyside/pysidesignal.cpp index 0c6a23245..150dd500e 100644 --- a/sources/pyside6/libpyside/pysidesignal.cpp +++ b/sources/pyside6/libpyside/pysidesignal.cpp @@ -18,6 +18,7 @@ #include <QtCore/QObject> #include <QtCore/QMetaMethod> #include <QtCore/QMetaObject> +#include <pep384ext.h> #include <signature.h> #include <algorithm> @@ -298,7 +299,7 @@ static void signalFree(void *vself) Py_XDECREF(self->homonymousMethod); self->homonymousMethod = nullptr; - Py_TYPE(pySelf)->tp_base->tp_free(self); + PepExt_TypeCallFree(Py_TYPE(pySelf)->tp_base, self); } static PyObject *signalGetItem(PyObject *obSelf, PyObject *key) @@ -368,7 +369,7 @@ static void signalInstanceFree(void *vself) self->d = nullptr; } self->deleted = true; - Py_TYPE(pySelf)->tp_base->tp_free(self); + PepExt_TypeCallFree(Py_TYPE(pySelf)->tp_base, self); } // PYSIDE-1523: PyFunction_Check is not accepting compiled functions and @@ -754,18 +755,16 @@ static PyObject *signalCall(PyObject *self, PyObject *args, PyObject *kw) return nullptr; } - descrgetfunc getDescriptor = Py_TYPE(signal->homonymousMethod)->tp_descr_get; - // Check if there exists a method with the same name as the signal, which is also a static // method in C++ land. - Shiboken::AutoDecRef homonymousMethod(getDescriptor(signal->homonymousMethod, - nullptr, nullptr)); + Shiboken::AutoDecRef homonymousMethod(PepExt_Type_CallDescrGet(signal->homonymousMethod, + nullptr, nullptr)); if (PyCFunction_Check(homonymousMethod.object()) && (PyCFunction_GET_FLAGS(homonymousMethod.object()) & METH_STATIC)) return PyObject_Call(homonymousMethod, args, kw); // Assumes homonymousMethod is not a static method. - ternaryfunc callFunc = Py_TYPE(signal->homonymousMethod)->tp_call; + ternaryfunc callFunc = PepExt_Type_GetCallSlot(Py_TYPE(signal->homonymousMethod)); return callFunc(homonymousMethod, args, kw); } @@ -822,8 +821,8 @@ static PyObject *signalInstanceCall(PyObject *self, PyObject *args, PyObject *kw return nullptr; } - descrgetfunc getDescriptor = Py_TYPE(hom)->tp_descr_get; - Shiboken::AutoDecRef homonymousMethod(getDescriptor(hom, PySideSignal->d->source, nullptr)); + Shiboken::AutoDecRef homonymousMethod(PepExt_Type_CallDescrGet(hom, PySideSignal->d->source, + nullptr)); return PyObject_Call(homonymousMethod, args, kw); } diff --git a/sources/pyside6/libpysideqml/pysideqmllistproperty.cpp b/sources/pyside6/libpysideqml/pysideqmllistproperty.cpp index a6f9f0193..97d6ce91b 100644 --- a/sources/pyside6/libpysideqml/pysideqmllistproperty.cpp +++ b/sources/pyside6/libpysideqml/pysideqmllistproperty.cpp @@ -5,6 +5,7 @@ #include "pysideqmlregistertype_p.h" #include <shiboken.h> +#include <pep384ext.h> #include <signature.h> #include <pysideproperty.h> @@ -33,7 +34,7 @@ extern "C" static PyObject *propList_tp_new(PyTypeObject *subtype, PyObject * /* args */, PyObject * /* kwds */) { - PySideProperty *me = reinterpret_cast<PySideProperty *>(subtype->tp_alloc(subtype, 0)); + auto *me = PepExt_TypeCallAlloc<PySideProperty>(subtype, 0); me->d = new QmlListPropertyPrivate; return reinterpret_cast<PyObject *>(me); } diff --git a/sources/shiboken6/libshiboken/CMakeLists.txt b/sources/shiboken6/libshiboken/CMakeLists.txt index 4638ca6f9..7a3c7d633 100644 --- a/sources/shiboken6/libshiboken/CMakeLists.txt +++ b/sources/shiboken6/libshiboken/CMakeLists.txt @@ -180,6 +180,7 @@ install(FILES sbkpython.h sbkwindows.h pep384impl.h + pep384ext.h voidptr.h bufferprocs_py37.h "${CMAKE_CURRENT_BINARY_DIR}/sbkversion.h" diff --git a/sources/shiboken6/libshiboken/basewrapper.cpp b/sources/shiboken6/libshiboken/basewrapper.cpp index 9a7d1d62d..bef687e41 100644 --- a/sources/shiboken6/libshiboken/basewrapper.cpp +++ b/sources/shiboken6/libshiboken/basewrapper.cpp @@ -5,6 +5,7 @@ #include "basewrapper_p.h" #include "bindingmanager.h" #include "helper.h" +#include "pep384ext.h" #include "sbkconverter.h" #include "sbkenum.h" #include "sbkerrors.h" @@ -55,7 +56,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); @@ -522,7 +523,7 @@ 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)); } @@ -1645,7 +1646,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) diff --git a/sources/shiboken6/libshiboken/pep384ext.h b/sources/shiboken6/libshiboken/pep384ext.h new file mode 100644 index 000000000..021c53d16 --- /dev/null +++ b/sources/shiboken6/libshiboken/pep384ext.h @@ -0,0 +1,89 @@ +// Copyright (C) 2024 The Qt Company Ltd. +// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only + +#ifndef PEP384EXT_H +#define PEP384EXT_H + +#include "pep384impl.h" + +/// Returns the allocator slot of the PyTypeObject. +inline allocfunc PepExt_Type_GetAllocSlot(PyTypeObject *t) +{ + return reinterpret_cast<allocfunc>(PepType_GetSlot(t, Py_tp_alloc)); +} + +/// Invokes the allocator slot of the PyTypeObject. +template <class Type> +inline Type *PepExt_TypeCallAlloc(PyTypeObject *t, Py_ssize_t nitems) +{ + PyObject *result = PepExt_Type_GetAllocSlot(t)(t, nitems); + return reinterpret_cast<Type *>(result); +} + +/// Returns the getattro slot of the PyTypeObject. +inline getattrofunc PepExt_Type_GetGetAttroSlot(PyTypeObject *t) +{ + return reinterpret_cast<getattrofunc>(PepType_GetSlot(t, Py_tp_getattro)); +} + +/// Returns the setattro slot of the PyTypeObject. +inline setattrofunc PepExt_Type_GetSetAttroSlot(PyTypeObject *t) +{ + return reinterpret_cast<setattrofunc>(PepType_GetSlot(t, Py_tp_setattro)); +} + +/// Returns the descr_get slot of the PyTypeObject. +inline descrgetfunc PepExt_Type_GetDescrGetSlot(PyTypeObject *t) +{ + return reinterpret_cast<descrgetfunc>(PepType_GetSlot(t, Py_tp_descr_get)); +} + +/// Invokes the descr_get slot of the PyTypeObject. +inline PyObject *PepExt_Type_CallDescrGet(PyObject *self, PyObject *obj, PyObject *type) +{ + return PepExt_Type_GetDescrGetSlot(Py_TYPE(self))(self, obj, type); +} + +/// Returns the descr_set slot of the PyTypeObject. +inline descrsetfunc PepExt_Type_GetDescrSetSlot(PyTypeObject *t) +{ + return reinterpret_cast<descrsetfunc>(PepType_GetSlot(t, Py_tp_descr_set)); +} + +/// Returns the call slot of the PyTypeObject. +inline ternaryfunc PepExt_Type_GetCallSlot(PyTypeObject *t) +{ + return reinterpret_cast<ternaryfunc>(PepType_GetSlot(t, Py_tp_call)); +} + +/// Returns the new slot of the PyTypeObject. +inline newfunc PepExt_Type_GetNewSlot(PyTypeObject *t) +{ + return reinterpret_cast<newfunc>(PepType_GetSlot(t, Py_tp_new)); +} + +/// Returns the init slot of the PyTypeObject. +inline initproc PepExt_Type_GetInitSlot(PyTypeObject *t) +{ + return reinterpret_cast<initproc>(PepType_GetSlot(t, Py_tp_init)); +} + +/// Returns the free slot of the PyTypeObject. +inline freefunc PepExt_Type_GetFreeSlot(PyTypeObject *t) +{ + return reinterpret_cast<freefunc>(PepType_GetSlot(t, Py_tp_free)); +} + +/// Invokes the free slot of the PyTypeObject. +inline void PepExt_TypeCallFree(PyTypeObject *t, void *object) +{ + PepExt_Type_GetFreeSlot(t)(object); +} + +/// Invokes the free slot of the PyTypeObject. +inline void PepExt_TypeCallFree(PyObject *object) +{ + PepExt_Type_GetFreeSlot(Py_TYPE(object))(object); +} + +#endif // PEP384EXT_H diff --git a/sources/shiboken6/libshiboken/sbkcontainer.h b/sources/shiboken6/libshiboken/sbkcontainer.h index 96faf95ee..240c772a9 100644 --- a/sources/shiboken6/libshiboken/sbkcontainer.h +++ b/sources/shiboken6/libshiboken/sbkcontainer.h @@ -63,7 +63,8 @@ public: static PyObject *tpNew(PyTypeObject *subtype, PyObject * /* args */, PyObject * /* kwds */) { - auto *me = reinterpret_cast<ShibokenContainer *>(subtype->tp_alloc(subtype, 0)); + allocfunc allocFunc = reinterpret_cast<allocfunc>(PepType_GetSlot(subtype, Py_tp_alloc)); + auto *me = reinterpret_cast<ShibokenContainer *>(allocFunc(subtype, 0)); auto *d = new ShibokenSequenceContainerPrivate; d->m_list = new SequenceContainer; d->m_ownsList = true; @@ -91,7 +92,9 @@ public: if (d->m_ownsList) delete d->m_list; delete d; - Py_TYPE(pySelf)->tp_base->tp_free(self); + auto freeFunc = reinterpret_cast<freefunc>(PepType_GetSlot(Py_TYPE(pySelf)->tp_base, + Py_tp_free)); + freeFunc(self); } static Py_ssize_t sqLen(PyObject *self) diff --git a/sources/shiboken6/libshiboken/sbkfeature_base.cpp b/sources/shiboken6/libshiboken/sbkfeature_base.cpp index 906df8e19..1bd4d6851 100644 --- a/sources/shiboken6/libshiboken/sbkfeature_base.cpp +++ b/sources/shiboken6/libshiboken/sbkfeature_base.cpp @@ -4,6 +4,7 @@ #include "basewrapper.h" #include "basewrapper_p.h" #include "autodecref.h" +#include "pep384ext.h" #include "sbkenum.h" #include "sbkstring.h" #include "sbkstaticstrings.h" @@ -300,7 +301,7 @@ PyObject *mangled_type_getattro(PyTypeObject *type, PyObject *name) * with the complex `tp_getattro` of `QObject` and other instances. * What we change here is the meta class of `QObject`. */ - static getattrofunc const type_getattro = PyType_Type.tp_getattro; + static getattrofunc const type_getattro = PepExt_Type_GetGetAttroSlot(&PyType_Type); static PyObject *const ignAttr1 = PyName::qtStaticMetaObject(); static PyObject *const ignAttr2 = PyMagicName::get(); static PyTypeObject *const EnumMeta = getPyEnumMeta(); diff --git a/sources/shiboken6/libshiboken/voidptr.cpp b/sources/shiboken6/libshiboken/voidptr.cpp index ed4f88ad1..7045b08b1 100644 --- a/sources/shiboken6/libshiboken/voidptr.cpp +++ b/sources/shiboken6/libshiboken/voidptr.cpp @@ -2,6 +2,7 @@ // SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only #include "voidptr.h" +#include "pep384ext.h" #include "sbkconverter.h" #include "basewrapper.h" #include "basewrapper_p.h" @@ -24,8 +25,7 @@ PyObject *SbkVoidPtrObject_new(PyTypeObject *type, PyObject * /* args */, PyObje // like this, actual call forgotten: // SbkVoidPtrObject *self = // reinterpret_cast<SbkVoidPtrObject *>(type->tp_alloc); - PyObject *ob = type->tp_alloc(type, 0); - auto *self = reinterpret_cast<SbkVoidPtrObject *>(ob); + auto *self = PepExt_TypeCallAlloc<SbkVoidPtrObject>(type, 0); if (self != nullptr) { self->cptr = nullptr; |