diff options
Diffstat (limited to 'sources/shiboken6/libshiboken/basewrapper.h')
-rw-r--r-- | sources/shiboken6/libshiboken/basewrapper.h | 228 |
1 files changed, 129 insertions, 99 deletions
diff --git a/sources/shiboken6/libshiboken/basewrapper.h b/sources/shiboken6/libshiboken/basewrapper.h index 2f0c22e9f..ec5545aea 100644 --- a/sources/shiboken6/libshiboken/basewrapper.h +++ b/sources/shiboken6/libshiboken/basewrapper.h @@ -1,47 +1,12 @@ -/**************************************************************************** -** -** Copyright (C) 2019 The Qt Company Ltd. -** Contact: https://www.qt.io/licensing/ -** -** This file is part of Qt for Python. -** -** $QT_BEGIN_LICENSE:LGPL$ -** Commercial License Usage -** Licensees holding valid commercial Qt licenses may use this file in -** accordance with the commercial license agreement provided with the -** Software or, alternatively, in accordance with the terms contained in -** a written agreement between you and The Qt Company. For licensing terms -** and conditions see https://www.qt.io/terms-conditions. For further -** information use the contact form at https://www.qt.io/contact-us. -** -** GNU Lesser General Public License Usage -** Alternatively, this file may be used under the terms of the GNU Lesser -** General Public License version 3 as published by the Free Software -** Foundation and appearing in the file LICENSE.LGPL3 included in the -** packaging of this file. Please review the following information to -** ensure the GNU Lesser General Public License version 3 requirements -** will be met: https://www.gnu.org/licenses/lgpl-3.0.html. -** -** GNU General Public License Usage -** Alternatively, this file may be used under the terms of the GNU -** General Public License version 2.0 or (at your option) the GNU General -** Public license version 3 or any later version approved by the KDE Free -** Qt Foundation. The licenses are as published by the Free Software -** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3 -** included in the packaging of this file. Please review the following -** information to ensure the GNU General Public License requirements will -** be met: https://www.gnu.org/licenses/gpl-2.0.html and -** https://www.gnu.org/licenses/gpl-3.0.html. -** -** $QT_END_LICENSE$ -** -****************************************************************************/ +// Copyright (C) 2019 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 BASEWRAPPER_H #define BASEWRAPPER_H #include "sbkpython.h" #include "shibokenmacros.h" +#include "sbktypefactory.h" #include <vector> #include <string> @@ -72,59 +37,60 @@ LIBSHIBOKEN_API void SbkDeallocWrapper(PyObject *pyObj); LIBSHIBOKEN_API void SbkDeallocQAppWrapper(PyObject *pyObj); LIBSHIBOKEN_API void SbkDeallocWrapperWithPrivateDtor(PyObject *self); -struct SbkObjectType; - /// Function signature for the multiple inheritance information initializers that should be provided by classes with multiple inheritance. -typedef int *(*MultipleInheritanceInitFunction)(const void *); +using MultipleInheritanceInitFunction = int *(*)(const void *); /** * Special cast function is used to correctly cast an object when it's * part of a multiple inheritance hierarchy. * The implementation of this function is auto generated by the generator and you don't need to care about it. */ -typedef void *(*SpecialCastFunction)(void *, SbkObjectType *); -typedef SbkObjectType *(*TypeDiscoveryFunc)(void *, SbkObjectType *); -typedef void *(*TypeDiscoveryFuncV2)(void *, SbkObjectType *); +using SpecialCastFunction = void *(*)(void *, PyTypeObject *); +using TypeDiscoveryFunc = PyTypeObject *(*)(void *, PyTypeObject *); +using TypeDiscoveryFuncV2 = void *(*)(void *, PyTypeObject *); // Used in userdata dealloc function -typedef void (*DeleteUserDataFunc)(void *); +using DeleteUserDataFunc = void (*)(void *); -typedef void (*ObjectDestructor)(void *); +using ObjectDestructor = void (*)(void *); -typedef void (*SubTypeInitHook)(SbkObjectType *, PyObject *, PyObject *); +using SubTypeInitHook = void (*)(PyTypeObject *, PyObject *, PyObject *); /// PYSIDE-1019: Set the function to select the current feature. /// Return value is the previous content. -typedef PyObject *(*SelectableFeatureHook)(PyTypeObject *); +using SelectableFeatureHook = void (*)(PyTypeObject *); +using SelectableFeatureCallback = void (*)(bool); LIBSHIBOKEN_API SelectableFeatureHook initSelectableFeature(SelectableFeatureHook func); +LIBSHIBOKEN_API void setSelectableFeatureCallback(SelectableFeatureCallback func); -// PYSIDE-1019: Get access to PySide reserved bits. -LIBSHIBOKEN_API int SbkObjectType_GetReserved(PyTypeObject *type); -LIBSHIBOKEN_API void SbkObjectType_SetReserved(PyTypeObject *type, int value); +/// PYSIDE-1626: Enforcing a context switch without further action. +LIBSHIBOKEN_API void SbkObjectType_UpdateFeature(PyTypeObject *type); -// PYSIDE-1019: Get access to PySide property strings. +/// PYSIDE-1019: Get access to PySide property strings. LIBSHIBOKEN_API const char **SbkObjectType_GetPropertyStrings(PyTypeObject *type); LIBSHIBOKEN_API void SbkObjectType_SetPropertyStrings(PyTypeObject *type, const char **strings); +/// PYSIDE-1735: Store the enumFlagInfo. +LIBSHIBOKEN_API void SbkObjectType_SetEnumFlagInfo(PyTypeObject *type, const char **strings); + /// PYSIDE-1470: Set the function to kill a Q*Application. -typedef void(*DestroyQAppHook)(); +using DestroyQAppHook = void(*)(); LIBSHIBOKEN_API void setDestroyQApplication(DestroyQAppHook func); +/// PYSIDE-535: Use the C API in PyPy instead of `op->ob_dict`, directly (borrowed ref) +LIBSHIBOKEN_API PyObject *SbkObject_GetDict_NoRef(PyObject *op); + extern LIBSHIBOKEN_API PyTypeObject *SbkObjectType_TypeF(void); -extern LIBSHIBOKEN_API SbkObjectType *SbkObject_TypeF(void); +extern LIBSHIBOKEN_API PyTypeObject *SbkObject_TypeF(void); struct SbkObjectTypePrivate; /// PyTypeObject extended with C++ multiple inheritance information. -struct LIBSHIBOKEN_API SbkObjectType -{ - PyTypeObject type; -}; -LIBSHIBOKEN_API PyObject *SbkObjectTpNew(PyTypeObject *subtype, PyObject *, PyObject *); +LIBSHIBOKEN_API PyObject *SbkObject_tp_new(PyTypeObject *subtype, PyObject *, PyObject *); /// The special case of a switchable singleton Q*Application. -LIBSHIBOKEN_API PyObject *SbkQAppTpNew(PyTypeObject *subtype, PyObject *, PyObject *); +LIBSHIBOKEN_API PyObject *SbkQApp_tp_new(PyTypeObject *subtype, PyObject *, PyObject *); /// Create a new Q*Application wrapper and monitor it. LIBSHIBOKEN_API PyObject *MakeQAppWrapper(PyTypeObject *type); @@ -133,20 +99,22 @@ LIBSHIBOKEN_API PyObject *MakeQAppWrapper(PyTypeObject *type); * PYSIDE-832: Use object_dealloc instead of nullptr. * * When moving to heaptypes, we were struck by a special default behavior of - * PyType_FromSpecWithBases that inserts subtype_dealloc when tp_dealloc is + * PyType_FromSpec that inserts subtype_dealloc when tp_dealloc is * nullptr. But the default before conversion to heaptypes was to assign * object_dealloc. This seems to be a bug in the Limited API. */ /// PYSIDE-939: Replaced by Sbk_object_dealloc. LIBSHIBOKEN_API PyObject *SbkDummyNew(PyTypeObject *type, PyObject *, PyObject *); -/// PYSIDE-1286: Generate correct __module__ and __qualname__ -LIBSHIBOKEN_API PyObject *SbkType_FromSpec(PyType_Spec *); -LIBSHIBOKEN_API PyObject *SbkType_FromSpecWithBases(PyType_Spec *, PyObject *); - /// PYSIDE-74: Fallback used in all types now. LIBSHIBOKEN_API PyObject *FallbackRichCompare(PyObject *self, PyObject *other, int op); +/// PYSIDE-1970: Be easily able to see what is happening in the running code. +LIBSHIBOKEN_API void disassembleFrame(const char *marker); + +/// PYSIDE-2230: Check if an object is an SbkObject. +LIBSHIBOKEN_API bool SbkObjectType_Check(PyTypeObject *type); + } // extern "C" namespace Shiboken @@ -157,6 +125,8 @@ namespace Shiboken */ LIBSHIBOKEN_API void init(); +/// PYSIDE-1415: Publish Shiboken objects. +LIBSHIBOKEN_API void initShibokenSupport(PyObject *module); /// Delete the class T allocated on \p cptr. template<typename T> @@ -165,11 +135,30 @@ void callCppDestructor(void *cptr) delete reinterpret_cast<T *>(cptr); } -// setErrorAboutWrongArguments now gets overload information from the signature module. -// The extra info argument can contain additional data about the error. +/// setErrorAboutWrongArguments now gets overload information from the signature module. +/// The extra info argument can contain additional data about the error. LIBSHIBOKEN_API void setErrorAboutWrongArguments(PyObject *args, const char *funcName, PyObject *info); +/// Return values for the different retun variants. +/// This is used instead of goto. +LIBSHIBOKEN_API PyObject *returnWrongArguments(PyObject *args, const char *funcName, + PyObject *info); + +LIBSHIBOKEN_API int returnWrongArguments_Zero(PyObject *args, const char *funcName, + PyObject *info); + +LIBSHIBOKEN_API int returnWrongArguments_MinusOne(PyObject *args, const char *funcName, + PyObject *info); + +/// A simple special version for the end of rich comparison. +LIBSHIBOKEN_API PyObject *returnFromRichCompare(PyObject *result); + +// Return error information object if the argument count is wrong +LIBSHIBOKEN_API PyObject *checkInvalidArgumentCount(Py_ssize_t numArgs, + Py_ssize_t minArgs, + Py_ssize_t maxArgs); + namespace ObjectType { /** @@ -195,38 +184,37 @@ LIBSHIBOKEN_API bool canCallConstructor(PyTypeObject *myType, PyTypeObject *ctor * \returns true if a call to ObjectType::cast() is needed to obtain the correct * C++ pointer for Python objects of type \p type. */ -LIBSHIBOKEN_API bool hasCast(SbkObjectType *type); +LIBSHIBOKEN_API bool hasCast(PyTypeObject *type); /** * Cast the C++ pointer held by a Python object \p obj of type \p sourceType, * to a C++ pointer of a C++ class indicated by type \p targetType. * \returns The cast C++ pointer. */ -LIBSHIBOKEN_API void *cast(SbkObjectType *sourceType, SbkObject *obj, PyTypeObject *targetType); +LIBSHIBOKEN_API void *cast(PyTypeObject *sourceType, SbkObject *obj, PyTypeObject *targetType); /// Set the C++ cast function for \p type. -LIBSHIBOKEN_API void setCastFunction(SbkObjectType *type, SpecialCastFunction func); - -LIBSHIBOKEN_API void setOriginalName(SbkObjectType *self, const char *name); -LIBSHIBOKEN_API const char *getOriginalName(SbkObjectType *self); +LIBSHIBOKEN_API void setCastFunction(PyTypeObject *type, SpecialCastFunction func); -LIBSHIBOKEN_API void setTypeDiscoveryFunctionV2(SbkObjectType *self, TypeDiscoveryFuncV2 func); -LIBSHIBOKEN_API void copyMultipleInheritance(SbkObjectType *self, SbkObjectType *other); -LIBSHIBOKEN_API void setMultipleInheritanceFunction(SbkObjectType *self, MultipleInheritanceInitFunction func); -LIBSHIBOKEN_API MultipleInheritanceInitFunction getMultipleInheritanceFunction(SbkObjectType *self); +LIBSHIBOKEN_API void setOriginalName(PyTypeObject *self, const char *name); +LIBSHIBOKEN_API const char *getOriginalName(PyTypeObject *self); -LIBSHIBOKEN_API void setDestructorFunction(SbkObjectType *self, ObjectDestructor func); +LIBSHIBOKEN_API void setTypeDiscoveryFunctionV2(PyTypeObject *self, TypeDiscoveryFuncV2 func); +LIBSHIBOKEN_API void copyMultipleInheritance(PyTypeObject *self, PyTypeObject *other); +LIBSHIBOKEN_API void setMultipleInheritanceFunction(PyTypeObject *self, MultipleInheritanceInitFunction func); +LIBSHIBOKEN_API MultipleInheritanceInitFunction getMultipleInheritanceFunction(PyTypeObject *type); -LIBSHIBOKEN_API void initPrivateData(SbkObjectType *self); +LIBSHIBOKEN_API void setDestructorFunction(PyTypeObject *self, ObjectDestructor func); enum WrapperFlags { InnerClass = 0x1, - DeleteInMainThread = 0x2 + DeleteInMainThread = 0x2, + Value = 0x4 }; /** * Initializes a Shiboken wrapper type and adds it to the module, * or to the enclosing class if the type is an inner class. - * This function also calls initPrivateData and setDestructorFunction. + * This function also calls setDestructorFunction. * \param enclosingObject The module or enclosing class to where the new \p type will be added. * \param typeName Name by which the type will be known in Python. * \param originalName Original C++ name of the type. @@ -240,14 +228,13 @@ enum WrapperFlags * wrapper type. * \returns true if the initialization went fine, false otherwise. */ -LIBSHIBOKEN_API SbkObjectType *introduceWrapperType(PyObject *enclosingObject, - const char *typeName, - const char *originalName, - PyType_Spec *typeSpec, - ObjectDestructor cppObjDtor, - SbkObjectType *baseType, - PyObject *baseTypes, - unsigned wrapperFlags = 0); +LIBSHIBOKEN_API PyTypeObject *introduceWrapperType(PyObject *enclosingObject, + const char *typeName, + const char *originalName, + PyType_Spec *typeSpec, + ObjectDestructor cppObjDtor, + PyObject *bases, + unsigned wrapperFlags = 0); /** * Set the subtype init hook for a type. @@ -256,28 +243,36 @@ LIBSHIBOKEN_API SbkObjectType *introduceWrapperType(PyObject *enclosingObject, * The hook gets 3 params, they are: The new type being created, args and kwds. The last two are the very * same got from tp_new. */ -LIBSHIBOKEN_API void setSubTypeInitHook(SbkObjectType *self, SubTypeInitHook func); +LIBSHIBOKEN_API void setSubTypeInitHook(PyTypeObject *self, SubTypeInitHook func); /** * Get the user data previously set by Shiboken::Object::setTypeUserData */ -LIBSHIBOKEN_API void *getTypeUserData(SbkObjectType *self); -LIBSHIBOKEN_API void setTypeUserData(SbkObjectType *self, void *userData, DeleteUserDataFunc d_func); +LIBSHIBOKEN_API void *getTypeUserData(PyTypeObject *self); +LIBSHIBOKEN_API void setTypeUserData(PyTypeObject *self, void *userData, DeleteUserDataFunc d_func); /** - * Return an instance of SbkObjectType for a C++ type name as determined by + * Return an instance of PyTypeObject for a C++ type name as determined by * typeinfo().name(). * \param typeName Type name * \since 5.12 */ -LIBSHIBOKEN_API SbkObjectType *typeForTypeName(const char *typeName); +LIBSHIBOKEN_API PyTypeObject *typeForTypeName(const char *typeName); /** - * Returns whether SbkObjectType has a special cast function (multiple inheritance) + * Returns whether PyTypeObject has a special cast function (multiple inheritance) * \param sbkType Sbk type * \since 5.12 */ -LIBSHIBOKEN_API bool hasSpecialCastFunction(SbkObjectType *sbkType); +LIBSHIBOKEN_API bool hasSpecialCastFunction(PyTypeObject *sbkType); + +/// Returns whether a C++ pointer of \p baseType can be safely downcast +/// to \p targetType (base is a direct, single line base class of targetType). +/// (is a direct, single-line inheritance) +/// \param baseType Python type of base class +/// \param targetType Python type of derived class +/// \since 6.8 +LIBSHIBOKEN_API bool canDowncastTo(PyTypeObject *baseType, PyTypeObject *targetType); } namespace Object { @@ -307,10 +302,11 @@ LIBSHIBOKEN_API Py_hash_t hash(PyObject *pyObj); * Find a child of given wrapper having same address having the specified type. */ LIBSHIBOKEN_API SbkObject *findColocatedChild(SbkObject *wrapper, - const SbkObjectType *instanceType); + const PyTypeObject *instanceType); /** - * Bind a C++ object to Python. + * Bind a C++ object to Python. Forwards to + * newObjectWithHeuristics(), newObjectForType() depending on \p isExactType. * \param instanceType equivalent Python type for the C++ object. * \param hasOwnership if true, Python will try to delete the underlying C++ object when there's no more refs. * \param isExactType if false, Shiboken will use some heuristics to detect the correct Python type of this C++ @@ -318,12 +314,46 @@ LIBSHIBOKEN_API SbkObject *findColocatedChild(SbkObject *wrapper, * and as fallback. * \param typeName If non-null, this will be used as helper to find the correct Python type for this object. */ -LIBSHIBOKEN_API PyObject *newObject(SbkObjectType *instanceType, +LIBSHIBOKEN_API PyObject *newObject(PyTypeObject *instanceType, void *cptr, bool hasOwnership = true, bool isExactType = false, const char *typeName = nullptr); +/// Bind a C++ object to Python for polymorphic pointers. Calls +/// newObjectWithHeuristics() with an additional check for multiple +/// inheritance, in which case it will fall back to instanceType. +/// \param instanceType Equivalent Python type for the C++ object. +/// \param hasOwnership if true, Python will try to delete the underlying C++ object +/// when there's no more refs. +/// \param typeName If non-null, this will be used as helper to find the correct +/// Python type for this object (obtained by typeid().name(). +LIBSHIBOKEN_API PyObject *newObjectForPointer(PyTypeObject *instanceType, + void *cptr, + bool hasOwnership = true, + const char *typeName = nullptr); + +/// Bind a C++ object to Python using some heuristics to detect the correct +/// Python type of this C++ object. In any case \p instanceType must be provided; +/// it'll be used as search starting point and as fallback. +/// \param instanceType Equivalent Python type for the C++ object. +/// \param hasOwnership if true, Python will try to delete the underlying C++ object +/// C++ object when there are no more references. +/// when there's no more refs. +/// \param typeName If non-null, this will be used as helper to find the correct +/// Python type for this object (obtained by typeid().name(). +LIBSHIBOKEN_API PyObject *newObjectWithHeuristics(PyTypeObject *instanceType, + void *cptr, + bool hasOwnership = true, + const char *typeName = nullptr); + +/// Bind a C++ object to Python using the given type. +/// \param instanceType Equivalent Python type for the C++ object. +/// \param hasOwnership if true, Python will try to delete the underlying +/// C++ object when there are no more references. +LIBSHIBOKEN_API PyObject *newObjectForType(PyTypeObject *instanceType, + void *cptr, bool hasOwnership = true); + /** * Changes the valid flag of a PyObject, invalid objects will raise an exception when someone tries to access it. */ |