diff options
Diffstat (limited to 'sources/shiboken2/libshiboken')
63 files changed, 0 insertions, 15752 deletions
diff --git a/sources/shiboken2/libshiboken/CMakeLists.txt b/sources/shiboken2/libshiboken/CMakeLists.txt deleted file mode 100644 index 752613417..000000000 --- a/sources/shiboken2/libshiboken/CMakeLists.txt +++ /dev/null @@ -1,158 +0,0 @@ -project(libshiboken) - -macro(get_numpy_location) - execute_process( - COMMAND ${PYTHON_EXECUTABLE} -c "if True: - import sys - import os - numpy = '' - for p in sys.path: - if 'site-' in p: - numpy = os.path.join(p, 'numpy') - if os.path.exists(numpy): - print(os.path.realpath(numpy)) - break" - OUTPUT_VARIABLE PYTHON_NUMPY_LOCATION - OUTPUT_STRIP_TRAILING_WHITESPACE) - message(STATUS "PYTHON_NUMPY_LOCATION: " ${PYTHON_NUMPY_LOCATION}) -endmacro() - -option(ENABLE_VERSION_SUFFIX "Used to use current version in suffix to generated files. This is used to allow multiples versions installed simultaneous." FALSE) -if(ENABLE_VERSION_SUFFIX) - set(shiboken2_SUFFIX "-${shiboken_MAJOR_VERSION}.${shiboken_MINOR_VERSION}") -else() - set(shiboken2_SUFFIX "") -endif() - -configure_file("${CMAKE_CURRENT_SOURCE_DIR}/sbkversion.h.in" - "${CMAKE_CURRENT_BINARY_DIR}/sbkversion.h" @ONLY) -configure_file("${CMAKE_CURRENT_SOURCE_DIR}/embed/signature_bootstrap.py" - "${CMAKE_CURRENT_BINARY_DIR}/embed/signature_bootstrap.py" @ONLY) - -add_custom_command( - OUTPUT "${CMAKE_CURRENT_BINARY_DIR}/embed/signature_bootstrap_inc.h" - OUTPUT "${CMAKE_CURRENT_BINARY_DIR}/embed/signature_inc.h" - COMMAND ${PYTHON_EXECUTABLE} -E - "${CMAKE_CURRENT_SOURCE_DIR}/embed/embedding_generator.py" - --cmake-dir "${CMAKE_CURRENT_BINARY_DIR}/embed" - --limited-api ${PYTHON_LIMITED_API}) - -set(libshiboken_MAJOR_VERSION ${shiboken_MAJOR_VERSION}) -set(libshiboken_MINOR_VERSION ${shiboken_MINOR_VERSION}) -set(libshiboken_MICRO_VERSION ${shiboken_MICRO_VERSION}) -set(libshiboken_VERSION "${libshiboken_MAJOR_VERSION}.${libshiboken_MINOR_VERSION}.${libshiboken_MICRO_VERSION}") -set(libshiboken_SOVERSION "${shiboken2_library_so_version}") - -set(libshiboken_SRC -basewrapper.cpp -debugfreehook.cpp -gilstate.cpp -helper.cpp -sbkarrayconverter.cpp -sbkconverter.cpp -sbkenum.cpp -sbkmodule.cpp -sbkstring.cpp -sbkstaticstrings.cpp -bindingmanager.cpp -threadstatesaver.cpp -shibokenbuffer.cpp -qapp_macro.cpp -pep384impl.cpp -voidptr.cpp -bufferprocs_py37.cpp - -embed/signature_bootstrap_inc.h -embed/signature_inc.h - -signature/signature.cpp -signature/signature_globals.cpp -signature/signature_extend.cpp -signature/signature_helper.cpp -) - -get_numpy_location() - -if (NOT "${PYTHON_NUMPY_LOCATION}" STREQUAL "") - list(APPEND libshiboken_SRC sbknumpyarrayconverter.cpp) -endif() - -set(APIEXTRACTOR_EXTRA_INCLUDES ${APIEXTRACTOR_EXTRA_INCLUDES} ${LIBXSLT_INCLUDE_DIR} ${LIBXML2_INCLUDE_DIR}) - -add_library(libshiboken SHARED ${libshiboken_SRC}) -add_library(Shiboken2::libshiboken ALIAS libshiboken) - -target_include_directories(libshiboken PUBLIC - $<BUILD_INTERFACE:${CMAKE_CURRENT_SOURCE_DIR}> - $<BUILD_INTERFACE:${CMAKE_CURRENT_BINARY_DIR}> - $<INSTALL_INTERFACE:include/shiboken2> -) - -if (NOT "${PYTHON_NUMPY_LOCATION}" STREQUAL "") - target_include_directories(libshiboken PRIVATE ${PYTHON_NUMPY_LOCATION}/core/include) - target_compile_definitions(libshiboken PRIVATE -DHAVE_NUMPY - PRIVATE -DNPY_NO_DEPRECATED_API=NPY_1_7_API_VERSION) - -endif() - -shiboken_compute_python_includes() -# On Windows we need to link against the python.lib import library. -# On macOS and Linux we don't link against the python shared / static library, -# the dynamic linker will pick up the python symbols at runtime automatically. -shiboken_compute_python_libraries() - -if(PYTHON_LIMITED_API) - target_compile_definitions(libshiboken PUBLIC "-DPy_LIMITED_API=0x03050000") -endif() - -if(CMAKE_BUILD_TYPE STREQUAL "Debug") - if(PYTHON_WITH_DEBUG) - target_compile_definitions(libshiboken PUBLIC "-DPy_DEBUG") - endif() - if (PYTHON_WITH_COUNT_ALLOCS) - target_compile_definitions(libshiboken PUBLIC "-DCOUNT_ALLOCS") - endif() -elseif(CMAKE_BUILD_TYPE STREQUAL "Release") - target_compile_definitions(libshiboken PUBLIC "-DNDEBUG") -endif() - -set_target_properties(libshiboken PROPERTIES OUTPUT_NAME "shiboken2${shiboken2_SUFFIX}${PYTHON_SHARED_LIBRARY_SUFFIX}" - VERSION ${libshiboken_VERSION} - SOVERSION ${libshiboken_SOVERSION} - DEFINE_SYMBOL BUILD_LIBSHIBOKEN) - -install(FILES - autodecref.h - basewrapper.h - bindingmanager.h - gilstate.h - helper.h - sbkarrayconverter.h - sbkconverter.h - sbkenum.h - sbkmodule.h - python25compat.h - sbkdbg.h - sbkstring.h - sbkstaticstrings.h - shiboken.h - shibokenmacros.h - threadstatesaver.h - shibokenbuffer.h - sbkpython.h - pep384impl.h - qapp_macro.h - voidptr.h - bufferprocs_py37.h - "${CMAKE_CURRENT_BINARY_DIR}/sbkversion.h" - - signature.h - signature/signature_p.h - - DESTINATION include/shiboken2${shiboken2_SUFFIX}) -install(TARGETS libshiboken EXPORT Shiboken2Targets - LIBRARY DESTINATION "${LIB_INSTALL_DIR}" - ARCHIVE DESTINATION "${LIB_INSTALL_DIR}" - RUNTIME DESTINATION bin) -install(EXPORT Shiboken2Targets NAMESPACE Shiboken2:: - DESTINATION ${LIB_INSTALL_DIR}/cmake/Shiboken2-${shiboken2_VERSION}) diff --git a/sources/shiboken2/libshiboken/autodecref.h b/sources/shiboken2/libshiboken/autodecref.h deleted file mode 100644 index 498b1aec4..000000000 --- a/sources/shiboken2/libshiboken/autodecref.h +++ /dev/null @@ -1,111 +0,0 @@ -/**************************************************************************** -** -** Copyright (C) 2016 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$ -** -****************************************************************************/ - -#ifndef AUTODECREF_H -#define AUTODECREF_H - -#include "sbkpython.h" -#include "basewrapper.h" - -struct SbkObject; -namespace Shiboken -{ - -/** - * AutoDecRef holds a PyObject pointer and decrement its reference counter when destroyed. - */ -struct LIBSHIBOKEN_API AutoDecRef -{ -public: - AutoDecRef(const AutoDecRef &) = delete; - AutoDecRef(AutoDecRef &&) = delete; - AutoDecRef &operator=(const AutoDecRef &) = delete; - AutoDecRef &operator=(AutoDecRef &&) = delete; - - /** - * AutoDecRef constructor. - * \param pyobj A borrowed reference to a Python object - */ - explicit AutoDecRef(PyObject *pyObj) : m_pyObj(pyObj) {} - /** - * AutoDecRef constructor. - * \param pyobj A borrowed reference to a Python object - */ - explicit AutoDecRef(SbkObject *pyObj) : m_pyObj(reinterpret_cast<PyObject *>(pyObj)) {} - - /// Decref the borrowed python reference - ~AutoDecRef() - { - Py_XDECREF(m_pyObj); - } - - inline bool isNull() const { return m_pyObj == nullptr; } - /// Returns the pointer of the Python object being held. - inline PyObject *object() { return m_pyObj; } - inline operator PyObject *() { return m_pyObj; } -#ifndef Py_LIMITED_API - inline operator PyTupleObject *() { return reinterpret_cast<PyTupleObject *>(m_pyObj); } -#endif - inline operator bool() const { return m_pyObj != nullptr; } - inline PyObject *operator->() { return m_pyObj; } - - template<typename T> - T cast() - { - return reinterpret_cast<T>(m_pyObj); - } - - /** - * Decref the current borrowed python reference and borrow \p other. - */ - void reset(PyObject *other) - { - // Safely decref m_pyObj. See Py_XSETREF in object.h . - PyObject *_py_tmp = m_pyObj; - m_pyObj = other; - Py_XDECREF(_py_tmp); - } -private: - PyObject *m_pyObj; -}; - -} // namespace Shiboken - -#endif // AUTODECREF_H - diff --git a/sources/shiboken2/libshiboken/basewrapper.cpp b/sources/shiboken2/libshiboken/basewrapper.cpp deleted file mode 100644 index 9dfd87208..000000000 --- a/sources/shiboken2/libshiboken/basewrapper.cpp +++ /dev/null @@ -1,1907 +0,0 @@ -/**************************************************************************** -** -** 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$ -** -****************************************************************************/ - -#include "basewrapper.h" -#include "basewrapper_p.h" -#include "bindingmanager.h" -#include "helper.h" -#include "sbkconverter.h" -#include "sbkenum.h" -#include "sbkstring.h" -#include "sbkstaticstrings.h" -#include "sbkstaticstrings_p.h" -#include "autodecref.h" -#include "gilstate.h" -#include <string> -#include <cstring> -#include <cstddef> -#include <set> -#include <sstream> -#include <algorithm> -#include "threadstatesaver.h" -#include "signature.h" -#include "qapp_macro.h" -#include "voidptr.h" - -#include <iostream> - -#if defined(__APPLE__) -#include <dlfcn.h> -#endif - -namespace { - void _destroyParentInfo(SbkObject *obj, bool keepReference); -} - -static void callDestructor(const Shiboken::DtorAccumulatorVisitor::DestructorEntries &dts) -{ - for (const auto &e : dts) { - Shiboken::ThreadStateSaver threadSaver; - threadSaver.save(); - e.destructor(e.cppInstance); - } -} - -extern "C" -{ - -// PYSIDE-939: A general replacement for object_dealloc. -void Sbk_object_dealloc(PyObject *self) -{ - if (PepRuntime_38_flag) { - // PYSIDE-939: Handling references correctly. - // This was not needed before Python 3.8 (Python issue 35810) - Py_DECREF(Py_TYPE(self)); - } - Py_TYPE(self)->tp_free(self); -} - -static void SbkObjectTypeDealloc(PyObject *pyObj); -static PyObject *SbkObjectTypeTpNew(PyTypeObject *metatype, PyObject *args, PyObject *kwds); - -static SelectableFeatureHook SelectFeatureSet = nullptr; - -static PyObject *Sbk_TypeGet___dict__(PyTypeObject *type, void *context); // forward - -static int -check_set_special_type_attr(PyTypeObject *type, PyObject *value, const char *name) -{ - if (!(type->tp_flags & Py_TPFLAGS_HEAPTYPE)) { - PyErr_Format(PyExc_TypeError, - "can't set %s.%s", type->tp_name, name); - return 0; - } - if (!value) { - PyErr_Format(PyExc_TypeError, - "can't delete %s.%s", type->tp_name, name); - return 0; - } - return 1; -} - -// PYSIDE-1177: Add a setter to allow setting type doc. -static int -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); -} - -// 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. -static PyGetSetDef SbkObjectType_Type_getsetlist[] = { - {const_cast<char *>("__signature__"), (getter)Sbk_TypeGet___signature__}, - {const_cast<char *>("__doc__"), (getter)Sbk_TypeGet___doc__, (setter)type_set_doc}, - {const_cast<char *>("__dict__"), (getter)Sbk_TypeGet___dict__}, - {nullptr} // Sentinel -}; - -#if PY_VERSION_HEX < 0x03000000 - -static PyObject *SbkObjectType_repr(PyObject *type) -{ - Shiboken::AutoDecRef mod(PyObject_GetAttr(type, Shiboken::PyMagicName::module())); - if (mod.isNull()) - return nullptr; - Shiboken::AutoDecRef name(PyObject_GetAttr(type, Shiboken::PyMagicName::qualname())); - if (name.isNull()) - return nullptr; - return PyString_FromFormat("<class '%s.%s'>", - PyString_AS_STRING(mod.object()), - PyString_AS_STRING(name.object())); -} - -#endif // PY_VERSION_HEX < 0x03000000 - -static PyObject *(*type_getattro)(PyObject *type, PyObject *name); // forward -static PyObject *mangled_type_getattro(PyTypeObject *type, PyObject *name); // forward - -static PyType_Slot SbkObjectType_Type_slots[] = { - {Py_tp_dealloc, reinterpret_cast<void *>(SbkObjectTypeDealloc)}, - {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 *>(SbkObjectTypeTpNew)}, - {Py_tp_free, reinterpret_cast<void *>(PyObject_GC_Del)}, - {Py_tp_getset, reinterpret_cast<void *>(SbkObjectType_Type_getsetlist)}, -#if PY_VERSION_HEX < 0x03000000 - {Py_tp_repr, reinterpret_cast<void *>(SbkObjectType_repr)}, -#endif - {0, nullptr} -}; -static PyType_Spec SbkObjectType_Type_spec = { - "1:Shiboken.ObjectType", - 0, // basicsize (inserted later) - sizeof(PyMemberDef), - Py_TPFLAGS_DEFAULT|Py_TPFLAGS_BASETYPE, - SbkObjectType_Type_slots, -}; - - -#if PY_VERSION_HEX < 0x03000000 -/***************************************************************************** - * - * PYSIDE-816: Workaround for Python 2.7 for SbkObjectType_TypeF(). - * - * This is an add-on for function typeobject.c:tp_new_wrapper from Python 2.7 . - * Problem: - * In Python 3.X, tp_new_wrapper uses this check: - - while (staticbase && (staticbase->tp_new == slot_tp_new)) - - * In Python 2.7, it uses this, instead: - - while (staticbase && (staticbase->tp_flags & Py_TPFLAGS_HEAPTYPE)) - - * The problem is that heap types have this unwanted dependency. - * But we cannot get at static slot_tp_new, and so we have to use - * the original function and patch Py_TPFLAGS_HEAPTYPE away during the call. - * - * PYSIDE-1051: The same problem holds for all dynamic metatypes generated by - * SbkObjectTypeTpNew() and all types generated by - * introduceWrapperType() . - * - * This led to a drastic overhaul of patch_tp_new_wrapper() which now adds - * the new wrapper to exactly those types which have the old wrapper. - */ - -ternaryfunc old_tp_new_wrapper = nullptr; - -static PyObject * -tp_new_wrapper(PyObject *self, PyObject *args, PyObject *kwds) -{ - PyTypeObject *type = reinterpret_cast<PyTypeObject *>(self); - Py_ssize_t orig_flags = type->tp_flags; - type->tp_flags &= ~Py_TPFLAGS_HEAPTYPE; - PyObject *ret = reinterpret_cast<ternaryfunc>(old_tp_new_wrapper)(self, args, kwds); - type->tp_flags = orig_flags; - return ret; -} - -// This is intentionally the __new__ docstring of Python 3.7 . -static struct PyMethodDef tp_new_methoddef[] = { - {"__new__", reinterpret_cast<PyCFunction>(tp_new_wrapper), METH_VARARGS|METH_KEYWORDS, - PyDoc_STR("__new__($type, *args, **kwargs)\n--\n\n" - "Create and return a new object. " - "See help(type) for accurate signature.")}, - {0} -}; - -static int -patch_tp_new_wrapper(PyTypeObject *type) -{ - /* - * The old tp_new_wrapper is added to all types that have tp_new. - * We patch that with a version that ignores the heaptype flag. - */ - auto newMethod = Shiboken::PyMagicName::new_(); - if (old_tp_new_wrapper == nullptr) { - PyObject *func = PyDict_GetItem(PyType_Type.tp_dict, newMethod); - assert(func); - PyCFunctionObject *pycf_ob = reinterpret_cast<PyCFunctionObject *>(func); - old_tp_new_wrapper = reinterpret_cast<ternaryfunc>(pycf_ob->m_ml->ml_meth); - } - PyObject *mro = type->tp_mro; - Py_ssize_t i, n = PyTuple_GET_SIZE(mro); - for (i = 0; i < n; i++) { - type = reinterpret_cast<PyTypeObject *>(PyTuple_GET_ITEM(mro, i)); - PyObject *existing = PyDict_GetItem(type->tp_dict, newMethod); - if (existing && PyCFunction_Check(existing) - && type->tp_flags & Py_TPFLAGS_HEAPTYPE) { - auto *pycf_ob = reinterpret_cast<PyCFunctionObject *>(existing); - auto existing_wrapper = reinterpret_cast<ternaryfunc>(pycf_ob->m_ml->ml_meth); - if (existing_wrapper == tp_new_wrapper) - break; - if (existing_wrapper == old_tp_new_wrapper) { - PyObject *ob_type = reinterpret_cast<PyObject *>(type); - Shiboken::AutoDecRef func(PyCFunction_New(tp_new_methoddef, ob_type)); - if (func.isNull() || PyDict_SetItem(type->tp_dict, newMethod, func)) - return -1; - } - } - } - return 0; -} -/*****************************************************************************/ -#endif // PY_VERSION_HEX < 0x03000000 - - -PyTypeObject *SbkObjectType_TypeF(void) -{ - static PyTypeObject *type = nullptr; - if (!type) { - // PYSIDE-1019: Insert the default tp_getattro explicitly here - // so we can overwrite it a bit. - type_getattro = PyType_Type.tp_getattro; - SbkObjectType_Type_spec.basicsize = - PepHeapType_SIZE + sizeof(SbkObjectTypePrivate); - type = reinterpret_cast<PyTypeObject *>(SbkType_FromSpec(&SbkObjectType_Type_spec)); -#if PY_VERSION_HEX < 0x03000000 - if (patch_tp_new_wrapper(type) < 0) - return nullptr; -#endif - } - return type; -} - -static PyObject *SbkObjectGetDict(PyObject *pObj, void *) -{ - auto *obj = reinterpret_cast<SbkObject *>(pObj); - if (!obj->ob_dict) - obj->ob_dict = PyDict_New(); - if (!obj->ob_dict) - return nullptr; - Py_INCREF(obj->ob_dict); - return obj->ob_dict; -} - -static PyGetSetDef SbkObjectGetSetList[] = { - {const_cast<char *>("__dict__"), SbkObjectGetDict, nullptr, nullptr, nullptr}, - {nullptr, nullptr, nullptr, nullptr, nullptr} // Sentinel -}; - -static int SbkObject_traverse(PyObject *self, visitproc visit, void *arg) -{ - auto *sbkSelf = reinterpret_cast<SbkObject *>(self); - - //Visit children - Shiboken::ParentInfo *pInfo = sbkSelf->d->parentInfo; - if (pInfo) { - for (SbkObject *c : pInfo->children) - Py_VISIT(c); - } - - //Visit refs - Shiboken::RefCountMap *rInfo = sbkSelf->d->referredObjects; - if (rInfo) { - for (auto it = rInfo->begin(), end = rInfo->end(); it != end; ++it) - Py_VISIT(it->second); - } - - if (sbkSelf->ob_dict) - Py_VISIT(sbkSelf->ob_dict); - return 0; -} - -static int SbkObject_clear(PyObject *self) -{ - auto *sbkSelf = reinterpret_cast<SbkObject *>(self); - - Shiboken::Object::removeParent(sbkSelf); - - if (sbkSelf->d->parentInfo) - _destroyParentInfo(sbkSelf, true); - - Shiboken::Object::clearReferences(sbkSelf); - - if (sbkSelf->ob_dict) - Py_CLEAR(sbkSelf->ob_dict); - return 0; -} - -static PyObject *SbkObject_GenericGetAttr(PyObject *obj, PyObject *name); -static int SbkObject_GenericSetAttr(PyObject *obj, PyObject *name, PyObject *value); - -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_traverse)}, - {Py_tp_clear, reinterpret_cast<void *>(SbkObject_clear)}, - // unsupported: {Py_tp_weaklistoffset, (void *)offsetof(SbkObject, weakreflist)}, - {Py_tp_getset, reinterpret_cast<void *>(SbkObjectGetSetList)}, - // 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, -}; - - -SbkObjectType *SbkObject_TypeF(void) -{ - static PyTypeObject *type = nullptr; - if (!type) { - type = reinterpret_cast<PyTypeObject *>(SbkType_FromSpec(&SbkObject_Type_spec)); - Py_TYPE(type) = SbkObjectType_TypeF(); - Py_INCREF(Py_TYPE(type)); - type->tp_weaklistoffset = offsetof(SbkObject, weakreflist); - type->tp_dictoffset = offsetof(SbkObject, ob_dict); - } - return reinterpret_cast<SbkObjectType *>(type); -} - -static int mainThreadDeletionHandler(void *) -{ - if (Py_IsInitialized()) - Shiboken::BindingManager::instance().runDeletionInMainThread(); - return 0; -} - -static void SbkDeallocWrapperCommon(PyObject *pyObj, bool canDelete) -{ - auto *sbkObj = reinterpret_cast<SbkObject *>(pyObj); - PyTypeObject *pyType = Py_TYPE(pyObj); - - // Need to decref the type if this is the dealloc func; if type - // is subclassed, that dealloc func will decref (see subtype_dealloc - // in typeobject.c in the python sources) - bool needTypeDecref = (false - || PyType_GetSlot(pyType, Py_tp_dealloc) == SbkDeallocWrapper - || PyType_GetSlot(pyType, Py_tp_dealloc) == SbkDeallocWrapperWithPrivateDtor); - if (PepRuntime_38_flag) { - // PYSIDE-939: Additional rule: Also when a subtype is heap allocated, - // then the subtype_dealloc deref will be suppressed, and we need again - // to supply a decref. - needTypeDecref |= (pyType->tp_base->tp_flags & Py_TPFLAGS_HEAPTYPE) != 0; - } - -#if defined(__APPLE__) - // Just checking once that our assumptions are right. - if (false) { - void *p = PyType_GetSlot(pyType, Py_tp_dealloc); - Dl_info dl_info; - dladdr(p, &dl_info); - fprintf(stderr, "tp_dealloc is %s\n", dl_info.dli_sname); - } - // Gives one of our functions - // "Sbk_object_dealloc" - // "SbkDeallocWrapperWithPrivateDtor" - // "SbkDeallocQAppWrapper" - // "SbkDeallocWrapper" - // but for typedealloc_test.py we get - // "subtype_dealloc" -#endif - - // Ensure that the GC is no longer tracking this object to avoid a - // possible reentrancy problem. Since there are multiple steps involved - // in deallocating a SbkObject it is possible for the garbage collector to - // be invoked and it trying to delete this object while it is still in - // progress from the first time around, resulting in a double delete and a - // crash. - // PYSIDE-571: Some objects do not use GC, so check this! - if (PyObject_IS_GC(pyObj)) - PyObject_GC_UnTrack(pyObj); - - // Check that Python is still initialized as sometimes this is called by a static destructor - // after Python interpeter is shutdown. - if (sbkObj->weakreflist && Py_IsInitialized()) - PyObject_ClearWeakRefs(pyObj); - - // If I have ownership and is valid delete C++ pointer - SbkObjectTypePrivate *sotp{nullptr}; - canDelete &= sbkObj->d->hasOwnership && sbkObj->d->validCppObject; - if (canDelete) { - sotp = PepType_SOTP(pyType); - if (sotp->delete_in_main_thread && Shiboken::currentThreadId() != Shiboken::mainThreadId()) { - auto &bindingManager = Shiboken::BindingManager::instance(); - if (sotp->is_multicpp) { - Shiboken::DtorAccumulatorVisitor visitor(sbkObj); - Shiboken::walkThroughClassHierarchy(Py_TYPE(pyObj), &visitor); - for (const auto &e : visitor.entries()) - bindingManager.addToDeletionInMainThread(e); - } else { - Shiboken::DestructorEntry e{sotp->cpp_dtor, sbkObj->d->cptr[0]}; - bindingManager.addToDeletionInMainThread(e); - } - Py_AddPendingCall(mainThreadDeletionHandler, nullptr); - canDelete = false; - } - } - - PyObject *error_type, *error_value, *error_traceback; - - /* Save the current exception, if any. */ - PyErr_Fetch(&error_type, &error_value, &error_traceback); - - if (canDelete) { - if (sotp->is_multicpp) { - Shiboken::DtorAccumulatorVisitor visitor(sbkObj); - Shiboken::walkThroughClassHierarchy(Py_TYPE(pyObj), &visitor); - Shiboken::Object::deallocData(sbkObj, true); - callDestructor(visitor.entries()); - } else { - void *cptr = sbkObj->d->cptr[0]; - Shiboken::Object::deallocData(sbkObj, true); - - Shiboken::ThreadStateSaver threadSaver; - if (Py_IsInitialized()) - threadSaver.save(); - sotp->cpp_dtor(cptr); - } - } else { - Shiboken::Object::deallocData(sbkObj, true); - } - - /* Restore the saved exception. */ - PyErr_Restore(error_type, error_value, error_traceback); - - if (needTypeDecref) - Py_DECREF(pyType); - if (PepRuntime_38_flag) { - // PYSIDE-939: Handling references correctly. - // This was not needed before Python 3.8 (Python issue 35810) - Py_DECREF(pyType); - } -} - -void SbkDeallocWrapper(PyObject *pyObj) -{ - SbkDeallocWrapperCommon(pyObj, true); -} - -void SbkDeallocQAppWrapper(PyObject *pyObj) -{ - SbkDeallocWrapper(pyObj); - // PYSIDE-571: make sure to create a singleton deleted qApp. - Py_DECREF(MakeQAppWrapper(nullptr)); -} - -void SbkDeallocWrapperWithPrivateDtor(PyObject *self) -{ - SbkDeallocWrapperCommon(self, false); -} - -void SbkObjectTypeDealloc(PyObject *pyObj) -{ - SbkObjectTypePrivate *sotp = PepType_SOTP(pyObj); - auto type = reinterpret_cast<PyTypeObject *>(pyObj); - - PyObject_GC_UnTrack(pyObj); -#ifndef Py_LIMITED_API - Py_TRASHCAN_SAFE_BEGIN(pyObj); -#endif - if (sotp) { - if (sotp->user_data && sotp->d_func) { - sotp->d_func(sotp->user_data); - sotp->user_data = nullptr; - } - free(sotp->original_name); - sotp->original_name = nullptr; - if (!Shiboken::ObjectType::isUserType(type)) - Shiboken::Conversions::deleteConverter(sotp->converter); - delete sotp; - sotp = nullptr; - } -#ifndef Py_LIMITED_API - Py_TRASHCAN_SAFE_END(pyObj); -#endif - if (PepRuntime_38_flag) { - // PYSIDE-939: Handling references correctly. - // This was not needed before Python 3.8 (Python issue 35810) - Py_DECREF(Py_TYPE(pyObj)); - } -} - -////////////////////////////////////////////////////////////////////////////// -// -// PYSIDE-1019: Support switchable extensions -// -// We simply exchange the complete class dicts. -// -// This is done in which replaces -// --------------- -------------- -// mangled_type_getattro type_getattro -// Sbk_TypeGet___dict__ type_dict -// SbkObject_GenericGetAttr PyObject_GenericGetAttr -// SbkObject_GenericSetAttr PyObject_GenericSetAttr -// - -void initSelectableFeature(SelectableFeatureHook func) -{ - SelectFeatureSet = func; -} - -static PyObject *mangled_type_getattro(PyTypeObject *type, PyObject *name) -{ - /* - * Note: This `type_getattro` version is only the default that comes - * from `PyType_Type.tp_getattro`. This does *not* interfere in any way - * with the complex `tp_getattro` of `QObject` and other instances. - * What we change here is the meta class of `QObject`. - */ - if (SelectFeatureSet != nullptr) - type->tp_dict = SelectFeatureSet(type); - return type_getattro(reinterpret_cast<PyObject *>(type), name); -} - -static PyObject *Sbk_TypeGet___dict__(PyTypeObject *type, void *context) -{ - /* - * This is the override for getting a dict. - */ - auto dict = type->tp_dict; - if (dict == NULL) - Py_RETURN_NONE; - if (SelectFeatureSet != nullptr) - dict = SelectFeatureSet(type); - return PyDictProxy_New(dict); -} - -// These functions replace the standard PyObject_Generic(Get|Set)Attr functions. -// They provide the default that "object" inherits. -// Everything else is directly handled by cppgenerator that calls `Feature::Select`. -static PyObject *SbkObject_GenericGetAttr(PyObject *obj, PyObject *name) -{ - auto type = Py_TYPE(obj); - if (SelectFeatureSet != nullptr) - type->tp_dict = SelectFeatureSet(type); - return PyObject_GenericGetAttr(obj, name); -} - -static int SbkObject_GenericSetAttr(PyObject *obj, PyObject *name, PyObject *value) -{ - auto type = Py_TYPE(obj); - if (SelectFeatureSet != nullptr) - type->tp_dict = SelectFeatureSet(type); - return PyObject_GenericSetAttr(obj, name, value); -} - -// Caching the select Id. -int SbkObjectType_GetReserved(PyTypeObject *type) -{ - auto ptr = PepType_SOTP(reinterpret_cast<SbkObjectType *>(type)); - // PYSIDE-1019: During import PepType_SOTP is still zero. - if (ptr == nullptr) - return -1; - return ptr->pyside_reserved_bits; -} - -void SbkObjectType_SetReserved(PyTypeObject *type, int value) -{ - PepType_SOTP(reinterpret_cast<SbkObjectType *>(type))->pyside_reserved_bits = value; -} - -const char **SbkObjectType_GetPropertyStrings(PyTypeObject *type) -{ - return PepType_SOTP(type)->propertyStrings; -} - -void SbkObjectType_SetPropertyStrings(PyTypeObject *type, const char **strings) -{ - PepType_SOTP(reinterpret_cast<SbkObjectType *>(type))->propertyStrings = strings; -} - -// -////////////////////////////////////////////////////////////////////////////// - -static PyObject *SbkObjectTypeTpNew(PyTypeObject *metatype, PyObject *args, PyObject *kwds) -{ - // Check if all bases are new style before calling type.tp_new - // Was causing gc assert errors in test_bug704.py when - // this check happened after creating the type object. - // Argument parsing take from type.tp_new code. - - // PYSIDE-595: Also check if all bases allow inheritance. - // Before we changed to heap types, it was sufficient to remove the - // Py_TPFLAGS_BASETYPE flag. That does not work, because PySide does - // not respect this flag itself! - PyObject *name; - PyObject *pyBases; - PyObject *dict; - static const char *kwlist[] = { "name", "bases", "dict", nullptr}; - - if (!PyArg_ParseTupleAndKeywords(args, kwds, "sO!O!:sbktype", const_cast<char **>(kwlist), - &name, - &PyTuple_Type, &pyBases, - &PyDict_Type, &dict)) - return nullptr; - - 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) { - // PYSIDE-595: A base class does not allow inheritance. - return SbkDummyNew(metatype, args, kwds); - } - } - - // The meta type creates a new type when the Python programmer extends a wrapped C++ class. - auto type_new = reinterpret_cast<newfunc>(PyType_Type.tp_new); - - // 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 = reinterpret_cast<SbkObjectType *>(type_new(metatype, args, kwds)); - PyMethodDescr_TypePtr->tp_flags = hold; - - if (!newType) - return nullptr; -#if PY_VERSION_HEX < 0x03000000 - // PYSIDE-1051: The newly created metatype needs the PYSIDE-816 wrapper, too. - if (patch_tp_new_wrapper(&newType->type) < 0) - return nullptr; -#endif - - Shiboken::ObjectType::initPrivateData(newType); - SbkObjectTypePrivate *sotp = PepType_SOTP(newType); - - const auto bases = Shiboken::getCppBaseClasses(reinterpret_cast<PyTypeObject *>(newType)); - if (bases.size() == 1) { - SbkObjectTypePrivate *parentType = PepType_SOTP(bases.front()); - sotp->mi_offsets = parentType->mi_offsets; - sotp->mi_init = parentType->mi_init; - sotp->mi_specialcast = parentType->mi_specialcast; - sotp->type_discovery = parentType->type_discovery; - sotp->cpp_dtor = parentType->cpp_dtor; - sotp->is_multicpp = 0; - sotp->converter = parentType->converter; - } else { - sotp->mi_offsets = nullptr; - sotp->mi_init = nullptr; - sotp->mi_specialcast = nullptr; - sotp->type_discovery = nullptr; - sotp->cpp_dtor = nullptr; - sotp->is_multicpp = 1; - sotp->converter = nullptr; - } - if (bases.size() == 1) - sotp->original_name = strdup(PepType_SOTP(bases.front())->original_name); - else - sotp->original_name = strdup("object"); - sotp->user_data = nullptr; - sotp->d_func = nullptr; - sotp->is_user_type = 1; - - for (SbkObjectType *base : bases) { - if (PepType_SOTP(base)->subtype_init) - PepType_SOTP(base)->subtype_init(newType, args, kwds); - } - return reinterpret_cast<PyObject *>(newType); -} - -static PyObject *_setupNew(SbkObject *self, PyTypeObject *subtype) -{ - Py_INCREF(reinterpret_cast<PyObject *>(subtype)); - auto d = new SbkObjectPrivate; - - SbkObjectTypePrivate *sotp = PepType_SOTP(subtype); - int numBases = ((sotp && sotp->is_multicpp) ? - Shiboken::getNumberOfCppBaseClasses(subtype) : 1); - d->cptr = new void *[numBases]; - std::memset(d->cptr, 0, sizeof(void *) *size_t(numBases)); - d->hasOwnership = 1; - d->containsCppWrapper = 0; - d->validCppObject = 0; - d->parentInfo = nullptr; - d->referredObjects = nullptr; - d->cppObjectCreated = 0; - self->ob_dict = nullptr; - self->weakreflist = nullptr; - self->d = d; - return reinterpret_cast<PyObject *>(self); -} - -PyObject *SbkObjectTpNew(PyTypeObject *subtype, PyObject *, PyObject *) -{ - SbkObject *self = PyObject_GC_New(SbkObject, subtype); - PyObject *res = _setupNew(self, subtype); - PyObject_GC_Track(reinterpret_cast<PyObject *>(self)); - return res; -} - -PyObject *SbkQAppTpNew(PyTypeObject *subtype, PyObject *, PyObject *) -{ - // PYSIDE-571: - // For qApp, we need to create a singleton Python object. - // We cannot track this with the GC, because it is a static variable! - - // Python 2 has a weird handling of flags in derived classes that Python 3 - // does not have. Observed with bug_307.py. - // But it could theoretically also happen with Python3. - // Therefore we enforce that there is no GC flag, ever! - - // PYSIDE-560: - // We avoid to use this in Python 3, because we have a hard time to get - // write access to these flags - auto self = reinterpret_cast<SbkObject *>(MakeQAppWrapper(subtype)); - return self == nullptr ? nullptr : _setupNew(self, subtype); -} - -PyObject *SbkDummyNew(PyTypeObject *type, PyObject *, PyObject *) -{ - // PYSIDE-595: Give the same error as type_call does when tp_new is NULL. - PyErr_Format(PyExc_TypeError, - "cannot create '%.100s' instances ¯\\_(ツ)_/¯", - type->tp_name); - return nullptr; -} - -PyObject *SbkType_FromSpec(PyType_Spec *spec) -{ - return SbkType_FromSpecWithBases(spec, nullptr); -} - -PyObject *SbkType_FromSpecWithBases(PyType_Spec *spec, PyObject *bases) -{ - // PYSIDE-1286: Generate correct __module__ and __qualname__ - // The name field can now be extended by an "n:" prefix which is - // the number of modules in the name. The default is 1. - // - // Example: - // "2:mainmod.submod.mainclass.subclass" - // results in - // __module__ : "mainmod.submod" - // __qualname__ : "mainclass.subclass" - // __name__ : "subclass" - - PyType_Spec new_spec = *spec; - const char *colon = strchr(spec->name, ':'); - assert(colon); - int package_level = atoi(spec->name); - const char *mod = new_spec.name = colon + 1; - - PyObject *type = PyType_FromSpecWithBases(&new_spec, bases); - if (type == nullptr) - return nullptr; - - const char *qual = mod; - for (int idx = package_level; idx > 0; --idx) { - const char *dot = strchr(qual, '.'); - if (!dot) - break; - qual = dot + 1; - } - int mlen = qual - mod - 1; - Shiboken::AutoDecRef module(Shiboken::String::fromCString(mod, mlen)); - Shiboken::AutoDecRef qualname(Shiboken::String::fromCString(qual)); - if (PyObject_SetAttr(type, Shiboken::PyMagicName::module(), module) < 0) - return nullptr; - if (PyObject_SetAttr(type, Shiboken::PyMagicName::qualname(), qualname) < 0) - return nullptr; - return type; -} - -// PYSIDE-74: Fallback used in all types now. -PyObject *FallbackRichCompare(PyObject *self, PyObject *other, int op) -{ - // This is a very simple implementation that supplies a simple identity. - static const char * const opstrings[] = {"<", "<=", "==", "!=", ">", ">="}; - PyObject *res; - - switch (op) { - - case Py_EQ: - res = (self == other) ? Py_True : Py_False; - break; - case Py_NE: - res = (self != other) ? Py_True : Py_False; - break; - default: - PyErr_Format(PyExc_TypeError, - "'%s' not supported between instances of '%.100s' and '%.100s'", - opstrings[op], - self->ob_type->tp_name, - other->ob_type->tp_name); - return NULL; - } - Py_INCREF(res); - return res; -} - -} //extern "C" - - -namespace -{ - -void _destroyParentInfo(SbkObject *obj, bool keepReference) -{ - Shiboken::ParentInfo *pInfo = obj->d->parentInfo; - if (pInfo) { - while(!pInfo->children.empty()) { - SbkObject *first = *pInfo->children.begin(); - // Mark child as invalid - Shiboken::Object::invalidate(first); - Shiboken::Object::removeParent(first, false, keepReference); - } - Shiboken::Object::removeParent(obj, false); - } -} - -} - -namespace Shiboken -{ -bool walkThroughClassHierarchy(PyTypeObject *currentType, HierarchyVisitor *visitor) -{ - PyObject *bases = currentType->tp_bases; - Py_ssize_t numBases = PyTuple_GET_SIZE(bases); - bool result = false; - for (int i = 0; !result && i < numBases; ++i) { - auto type = reinterpret_cast<PyTypeObject *>(PyTuple_GET_ITEM(bases, i)); - if (PyType_IsSubtype(type, reinterpret_cast<PyTypeObject *>(SbkObject_TypeF()))) { - auto sbkType = reinterpret_cast<SbkObjectType *>(type); - result = PepType_SOTP(sbkType)->is_user_type - ? walkThroughClassHierarchy(type, visitor) : visitor->visit(sbkType); - } - } - return result; -} - -// Wrapper metatype and base type ---------------------------------------------------------- - -HierarchyVisitor::HierarchyVisitor() = default; -HierarchyVisitor::~HierarchyVisitor() = default; - -bool BaseCountVisitor::visit(SbkObjectType *) -{ - m_count++; - return false; -} - -bool BaseAccumulatorVisitor::visit(SbkObjectType *node) -{ - m_bases.push_back(node); - return false; -} - -bool GetIndexVisitor::visit(SbkObjectType *node) -{ - m_index++; - return PyType_IsSubtype(reinterpret_cast<PyTypeObject *>(node), m_desiredType); -} - -bool DtorAccumulatorVisitor::visit(SbkObjectType *node) -{ - m_entries.push_back(DestructorEntry{PepType_SOTP(node)->cpp_dtor, - m_pyObject->d->cptr[m_entries.size()]}); - return false; -} - -void _initMainThreadId(); // helper.cpp - -namespace Conversions { void init(); } - -void init() -{ - static bool shibokenAlreadInitialised = false; - if (shibokenAlreadInitialised) - return; - - _initMainThreadId(); - - Conversions::init(); - -#if PY_VERSION_HEX < 0x03070000 - PyEval_InitThreads(); -#endif - - //Init private data - Pep384_Init(); - - Shiboken::ObjectType::initPrivateData(SbkObject_TypeF()); - - 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."); - - if (PyType_Ready(reinterpret_cast<PyTypeObject *>(SbkObject_TypeF())) < 0) - Py_FatalError("[libshiboken] Failed to initialize Shiboken.BaseWrapper type."); - - VoidPtr::init(); - - shibokenAlreadInitialised = true; -} - -// setErrorAboutWrongArguments now gets overload info from the signature module. -void setErrorAboutWrongArguments(PyObject *args, const char *funcName) -{ - SetError_Argument(args, funcName); -} - -class FindBaseTypeVisitor : public HierarchyVisitor -{ -public: - explicit FindBaseTypeVisitor(PyTypeObject *typeToFind) : m_typeToFind(typeToFind) {} - - bool visit(SbkObjectType *node) override - { - return reinterpret_cast<PyTypeObject *>(node) == m_typeToFind; - } - -private: - PyTypeObject *m_typeToFind; -}; - -std::vector<SbkObject *> splitPyObject(PyObject *pyObj) -{ - std::vector<SbkObject *> result; - if (PySequence_Check(pyObj)) { - AutoDecRef lst(PySequence_Fast(pyObj, "Invalid keep reference object.")); - if (!lst.isNull()) { - for (Py_ssize_t i = 0, i_max = PySequence_Fast_GET_SIZE(lst.object()); i < i_max; ++i) { - PyObject *item = PySequence_Fast_GET_ITEM(lst.object(), i); - if (Object::checkType(item)) - result.push_back(reinterpret_cast<SbkObject *>(item)); - } - } - } else { - result.push_back(reinterpret_cast<SbkObject *>(pyObj)); - } - return result; -} - -template <class Iterator> -inline void decRefPyObjectList(Iterator i1, Iterator i2) -{ - for (; i1 != i2; ++i1) - Py_DECREF(i1->second); -} - -namespace ObjectType -{ - -bool checkType(PyTypeObject *type) -{ - return PyType_IsSubtype(type, reinterpret_cast<PyTypeObject *>(SbkObject_TypeF())) != 0; -} - -bool isUserType(PyTypeObject *type) -{ - return checkType(type) && PepType_SOTP(type)->is_user_type; -} - -bool canCallConstructor(PyTypeObject *myType, PyTypeObject *ctorType) -{ - FindBaseTypeVisitor visitor(ctorType); - if (!walkThroughClassHierarchy(myType, &visitor)) { - PyErr_Format(PyExc_TypeError, "%s isn't a direct base class of %s", ctorType->tp_name, myType->tp_name); - return false; - } - return true; -} - -bool hasCast(SbkObjectType *type) -{ - return PepType_SOTP(type)->mi_specialcast != nullptr; -} - -void *cast(SbkObjectType *sourceType, SbkObject *obj, PyTypeObject *targetType) -{ - return PepType_SOTP(sourceType)->mi_specialcast(Object::cppPointer(obj, targetType), - reinterpret_cast<SbkObjectType *>(targetType)); -} - -void setCastFunction(SbkObjectType *type, SpecialCastFunction func) -{ - PepType_SOTP(type)->mi_specialcast = func; -} - -void setOriginalName(SbkObjectType *type, const char *name) -{ - SbkObjectTypePrivate *sotp = PepType_SOTP(type); - if (sotp->original_name) - free(sotp->original_name); - sotp->original_name = strdup(name); -} - -const char *getOriginalName(SbkObjectType *type) -{ - return PepType_SOTP(type)->original_name; -} - -void setTypeDiscoveryFunctionV2(SbkObjectType *type, TypeDiscoveryFuncV2 func) -{ - PepType_SOTP(type)->type_discovery = func; -} - -void copyMultipleInheritance(SbkObjectType *type, SbkObjectType *other) -{ - PepType_SOTP(type)->mi_init = PepType_SOTP(other)->mi_init; - PepType_SOTP(type)->mi_offsets = PepType_SOTP(other)->mi_offsets; - PepType_SOTP(type)->mi_specialcast = PepType_SOTP(other)->mi_specialcast; -} - -void setMultipleInheritanceFunction(SbkObjectType *type, MultipleInheritanceInitFunction function) -{ - PepType_SOTP(type)->mi_init = function; -} - -MultipleInheritanceInitFunction getMultipleInheritanceFunction(SbkObjectType *type) -{ - return PepType_SOTP(type)->mi_init; -} - -void setDestructorFunction(SbkObjectType *type, ObjectDestructor func) -{ - PepType_SOTP(type)->cpp_dtor = func; -} - -void initPrivateData(SbkObjectType *type) -{ - PepType_SOTP(type) = new SbkObjectTypePrivate; - memset(PepType_SOTP(type), 0, sizeof(SbkObjectTypePrivate)); -} - -SbkObjectType * -introduceWrapperType(PyObject *enclosingObject, - const char *typeName, - const char *originalName, - PyType_Spec *typeSpec, - ObjectDestructor cppObjDtor, - SbkObjectType *baseType, - PyObject *baseTypes, - unsigned wrapperFlags) -{ - typeSpec->slots[0].pfunc = reinterpret_cast<void *>(baseType ? baseType : SbkObject_TypeF()); - - PyObject *heaptype = SbkType_FromSpecWithBases(typeSpec, baseTypes); - Py_TYPE(heaptype) = SbkObjectType_TypeF(); - Py_INCREF(Py_TYPE(heaptype)); - auto *type = reinterpret_cast<SbkObjectType *>(heaptype); -#if PY_VERSION_HEX < 0x03000000 - // PYSIDE-1051: The newly created type needs the PYSIDE-816 wrapper, too. - if (patch_tp_new_wrapper(&type->type) < 0) - return nullptr; -#endif - if (baseType) { - if (baseTypes) { - for (int i = 0; i < PySequence_Fast_GET_SIZE(baseTypes); ++i) - BindingManager::instance().addClassInheritance(reinterpret_cast<SbkObjectType *>(PySequence_Fast_GET_ITEM(baseTypes, i)), type); - } else { - BindingManager::instance().addClassInheritance(baseType, type); - } - } - if (PyType_Ready(reinterpret_cast<PyTypeObject *>(type)) < 0) - return nullptr; - - initPrivateData(type); - auto sotp = PepType_SOTP(type); - if (wrapperFlags & DeleteInMainThread) - sotp->delete_in_main_thread = 1; - - setOriginalName(type, originalName); - setDestructorFunction(type, cppObjDtor); - auto *ob_type = reinterpret_cast<PyObject *>(type); - - if (wrapperFlags & InnerClass) - return PyDict_SetItemString(enclosingObject, typeName, ob_type) == 0 ? type : nullptr; - - // PyModule_AddObject steals type's reference. - Py_INCREF(ob_type); - if (PyModule_AddObject(enclosingObject, typeName, ob_type) != 0) { - std::cerr << "Warning: " << __FUNCTION__ << " returns nullptr for " - << typeName << '/' << originalName << " due to PyModule_AddObject(enclosingObject=" - << enclosingObject << ",ob_type=" << ob_type << ") failing\n"; - return nullptr; - } - return type; -} - -void setSubTypeInitHook(SbkObjectType *type, SubTypeInitHook func) -{ - PepType_SOTP(type)->subtype_init = func; -} - -void *getTypeUserData(SbkObjectType *type) -{ - return PepType_SOTP(type)->user_data; -} - -void setTypeUserData(SbkObjectType *type, void *userData, DeleteUserDataFunc d_func) -{ - SbkObjectTypePrivate *sotp = PepType_SOTP(type); - sotp->user_data = userData; - 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 - - -namespace Object -{ - -static void recursive_invalidate(SbkObject *self, std::set<SbkObject *>& seen); - -bool checkType(PyObject *pyObj) -{ - return ObjectType::checkType(Py_TYPE(pyObj)); -} - -bool isUserType(PyObject *pyObj) -{ - return ObjectType::isUserType(Py_TYPE(pyObj)); -} - -Py_hash_t hash(PyObject *pyObj) -{ - assert(Shiboken::Object::checkType(pyObj)); - return reinterpret_cast<Py_hash_t>(pyObj); -} - -static void setSequenceOwnership(PyObject *pyObj, bool owner) -{ - - bool has_length = true; - - if (!pyObj) - return; - - if (PySequence_Size(pyObj) < 0) { - PyErr_Clear(); - has_length = false; - } - - if (PySequence_Check(pyObj) && has_length) { - Py_ssize_t size = PySequence_Size(pyObj); - if (size > 0) { - const auto objs = splitPyObject(pyObj); - if (owner) { - for (SbkObject *o : objs) - getOwnership(o); - } else { - for (SbkObject *o : objs) - releaseOwnership(o); - } - } - } else if (Object::checkType(pyObj)) { - if (owner) - getOwnership(reinterpret_cast<SbkObject *>(pyObj)); - else - releaseOwnership(reinterpret_cast<SbkObject *>(pyObj)); - } -} - -void setValidCpp(SbkObject *pyObj, bool value) -{ - pyObj->d->validCppObject = value; -} - -void setHasCppWrapper(SbkObject *pyObj, bool value) -{ - pyObj->d->containsCppWrapper = value; -} - -bool hasCppWrapper(SbkObject *pyObj) -{ - return pyObj->d->containsCppWrapper; -} - -bool wasCreatedByPython(SbkObject *pyObj) -{ - return pyObj->d->cppObjectCreated; -} - -void callCppDestructors(SbkObject *pyObj) -{ - PyTypeObject *type = Py_TYPE(pyObj); - SbkObjectTypePrivate *sotp = PepType_SOTP(type); - if (sotp->is_multicpp) { - Shiboken::DtorAccumulatorVisitor visitor(pyObj); - Shiboken::walkThroughClassHierarchy(type, &visitor); - callDestructor(visitor.entries()); - } else { - Shiboken::ThreadStateSaver threadSaver; - threadSaver.save(); - sotp->cpp_dtor(pyObj->d->cptr[0]); - } - - /* invalidate needs to be called before deleting pointer array because - it needs to delete entries for them from the BindingManager hash table; - also release wrapper explicitly if object contains C++ wrapper because - invalidate doesn't */ - invalidate(pyObj); - if (pyObj->d->validCppObject && pyObj->d->containsCppWrapper) { - BindingManager::instance().releaseWrapper(pyObj); - } - - delete[] pyObj->d->cptr; - pyObj->d->cptr = nullptr; - pyObj->d->validCppObject = false; -} - -bool hasOwnership(SbkObject *pyObj) -{ - return pyObj->d->hasOwnership; -} - -void getOwnership(SbkObject *self) -{ - // skip if already have the ownership - if (self->d->hasOwnership) - return; - - // skip if this object has parent - if (self->d->parentInfo && self->d->parentInfo->parent) - return; - - // Get back the ownership - self->d->hasOwnership = true; - - if (self->d->containsCppWrapper) - Py_DECREF(reinterpret_cast<PyObject *>(self)); // Remove extra ref - else - makeValid(self); // Make the object valid again -} - -void getOwnership(PyObject *pyObj) -{ - if (pyObj) - setSequenceOwnership(pyObj, true); -} - -void releaseOwnership(SbkObject *self) -{ - // skip if the ownership have already moved to c++ - auto *selfType = reinterpret_cast<SbkObjectType *>(Py_TYPE(self)); - if (!self->d->hasOwnership || Shiboken::Conversions::pythonTypeIsValueType(PepType_SOTP(selfType)->converter)) - return; - - // remove object ownership - self->d->hasOwnership = false; - - // If We have control over object life - if (self->d->containsCppWrapper) - Py_INCREF(reinterpret_cast<PyObject *>(self)); // keep the python object alive until the wrapper destructor call - else - invalidate(self); // If I do not know when this object will die We need to invalidate this to avoid use after -} - -void releaseOwnership(PyObject *self) -{ - setSequenceOwnership(self, false); -} - -/* Needed forward declarations */ -static void recursive_invalidate(PyObject *pyobj, std::set<SbkObject *>& seen); -static void recursive_invalidate(SbkObject *self, std::set<SbkObject *> &seen); - -void invalidate(PyObject *pyobj) -{ - std::set<SbkObject *> seen; - recursive_invalidate(pyobj, seen); -} - -void invalidate(SbkObject *self) -{ - std::set<SbkObject *> seen; - recursive_invalidate(self, seen); -} - -static void recursive_invalidate(PyObject *pyobj, std::set<SbkObject *> &seen) -{ - const auto objs = splitPyObject(pyobj); - for (SbkObject *o : objs) - recursive_invalidate(o, seen); -} - -static void recursive_invalidate(SbkObject *self, std::set<SbkObject *> &seen) -{ - // Skip if this object not is a valid object or if it's already been seen - if (!self || reinterpret_cast<PyObject *>(self) == Py_None || seen.find(self) != seen.end()) - return; - seen.insert(self); - - if (!self->d->containsCppWrapper) { - self->d->validCppObject = false; // Mark object as invalid only if this is not a wrapper class - BindingManager::instance().releaseWrapper(self); - } - - // If it is a parent invalidate all children. - if (self->d->parentInfo) { - // Create a copy because this list can be changed during the process - ChildrenList copy = self->d->parentInfo->children; - - for (SbkObject *child : copy) { - // invalidate the child - recursive_invalidate(child, seen); - - // if the parent not is a wrapper class, then remove children from him, because We do not know when this object will be destroyed - if (!self->d->validCppObject) - removeParent(child, true, true); - } - } - - // If has ref to other objects invalidate all - if (self->d->referredObjects) { - RefCountMap &refCountMap = *(self->d->referredObjects); - for (auto it = refCountMap.begin(), end = refCountMap.end(); it != end; ++it) - recursive_invalidate(it->second, seen); - } -} - -void makeValid(SbkObject *self) -{ - // Skip if this object not is a valid object - if (!self || reinterpret_cast<PyObject *>(self) == Py_None || self->d->validCppObject) - return; - - // Mark object as invalid only if this is not a wrapper class - self->d->validCppObject = true; - - // If it is a parent make all children valid - if (self->d->parentInfo) { - for (SbkObject *child : self->d->parentInfo->children) - makeValid(child); - } - - // 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)); - } - } -} - -void *cppPointer(SbkObject *pyObj, PyTypeObject *desiredType) -{ - PyTypeObject *type = Py_TYPE(pyObj); - int idx = 0; - if (PepType_SOTP(reinterpret_cast<SbkObjectType *>(type))->is_multicpp) - idx = getTypeIndexOnHierarchy(type, desiredType); - if (pyObj->d->cptr) - return pyObj->d->cptr[idx]; - return nullptr; -} - -std::vector<void *> cppPointers(SbkObject *pyObj) -{ - int n = getNumberOfCppBaseClasses(Py_TYPE(pyObj)); - std::vector<void *> ptrs(n); - for (int i = 0; i < n; ++i) - ptrs[i] = pyObj->d->cptr[i]; - return ptrs; -} - - -bool setCppPointer(SbkObject *sbkObj, PyTypeObject *desiredType, void *cptr) -{ - int idx = 0; - PyTypeObject *type = Py_TYPE(sbkObj); - if (PepType_SOTP(type)->is_multicpp) - idx = getTypeIndexOnHierarchy(type, desiredType); - - const bool alreadyInitialized = sbkObj->d->cptr[idx] != nullptr; - if (alreadyInitialized) - PyErr_SetString(PyExc_RuntimeError, "You can't initialize an object twice!"); - else - sbkObj->d->cptr[idx] = cptr; - - sbkObj->d->cppObjectCreated = true; - return !alreadyInitialized; -} - -bool isValid(PyObject *pyObj) -{ - if (!pyObj || pyObj == Py_None - || Py_TYPE(Py_TYPE(pyObj)) != SbkObjectType_TypeF()) { - return true; - } - - auto priv = reinterpret_cast<SbkObject *>(pyObj)->d; - - if (!priv->cppObjectCreated && isUserType(pyObj)) { - PyErr_Format(PyExc_RuntimeError, "'__init__' method of object's base class (%s) not called.", - Py_TYPE(pyObj)->tp_name); - return false; - } - - if (!priv->validCppObject) { - PyErr_Format(PyExc_RuntimeError, "Internal C++ object (%s) already deleted.", - Py_TYPE(pyObj)->tp_name); - return false; - } - - return true; -} - -bool isValid(SbkObject *pyObj, bool throwPyError) -{ - if (!pyObj) - return false; - - SbkObjectPrivate *priv = pyObj->d; - if (!priv->cppObjectCreated && isUserType(reinterpret_cast<PyObject *>(pyObj))) { - if (throwPyError) - PyErr_Format(PyExc_RuntimeError, "Base constructor of the object (%s) not called.", - Py_TYPE(pyObj)->tp_name); - return false; - } - - if (!priv->validCppObject) { - if (throwPyError) - PyErr_Format(PyExc_RuntimeError, "Internal C++ object (%s) already deleted.", - (Py_TYPE(pyObj))->tp_name); - return false; - } - - return true; -} - -bool isValid(PyObject *pyObj, bool throwPyError) -{ - if (!pyObj || pyObj == Py_None || - !PyType_IsSubtype(Py_TYPE(pyObj), reinterpret_cast<PyTypeObject *>(SbkObject_TypeF()))) { - return true; - } - return isValid(reinterpret_cast<SbkObject *>(pyObj), throwPyError); -} - -SbkObject *findColocatedChild(SbkObject *wrapper, - const SbkObjectType *instanceType) -{ - // Degenerate case, wrapper is the correct wrapper. - if (reinterpret_cast<const void *>(Py_TYPE(wrapper)) == reinterpret_cast<const void *>(instanceType)) - return wrapper; - - if (!(wrapper->d && wrapper->d->cptr)) - return nullptr; - - ParentInfo *pInfo = wrapper->d->parentInfo; - if (!pInfo) - return nullptr; - - ChildrenList &children = pInfo->children; - - for (SbkObject *child : children) { - if (!(child->d && child->d->cptr)) - continue; - if (child->d->cptr[0] == wrapper->d->cptr[0]) { - return reinterpret_cast<const void *>(Py_TYPE(child)) == reinterpret_cast<const void *>(instanceType) - ? child : findColocatedChild(child, instanceType); - } - } - return nullptr; -} - -PyObject *newObject(SbkObjectType *instanceType, - void *cptr, - bool hasOwnership, - bool isExactType, - const char *typeName) -{ - // Try to find the exact type of cptr. - if (!isExactType) { - if (SbkObjectType *exactType = ObjectType::typeForTypeName(typeName)) - instanceType = exactType; - else - instanceType = BindingManager::instance().resolveType(&cptr, instanceType); - } - - bool shouldCreate = true; - bool shouldRegister = true; - SbkObject *self = nullptr; - - // Some logic to ensure that colocated child field does not overwrite the parent - if (BindingManager::instance().hasWrapper(cptr)) { - SbkObject *existingWrapper = BindingManager::instance().retrieveWrapper(cptr); - - self = findColocatedChild(existingWrapper, instanceType); - if (self) { - // Wrapper already registered for cptr. - // This should not ideally happen, binding code should know when a wrapper - // already exists and retrieve it instead. - shouldRegister = shouldCreate = false; - } else if (hasOwnership && - (!(Shiboken::Object::hasCppWrapper(existingWrapper) || - Shiboken::Object::hasOwnership(existingWrapper)))) { - // Old wrapper is likely junk, since we have ownership and it doesn't. - BindingManager::instance().releaseWrapper(existingWrapper); - } else { - // Old wrapper may be junk caused by some bug in identifying object deletion - // but it may not be junk when a colocated field is accessed for an - // object which was not created by python (returned from c++ factory function). - // Hence we cannot release the wrapper confidently so we do not register. - shouldRegister = false; - } - } - - if (shouldCreate) { - self = reinterpret_cast<SbkObject *>(SbkObjectTpNew(reinterpret_cast<PyTypeObject *>(instanceType), nullptr, nullptr)); - self->d->cptr[0] = cptr; - self->d->hasOwnership = hasOwnership; - self->d->validCppObject = 1; - if (shouldRegister) { - BindingManager::instance().registerWrapper(self, cptr); - } - } else { - Py_IncRef(reinterpret_cast<PyObject *>(self)); - } - return reinterpret_cast<PyObject *>(self); -} - -void destroy(SbkObject *self, void *cppData) -{ - // Skip if this is called with NULL pointer this can happen in derived classes - if (!self) - return; - - // This can be called in c++ side - Shiboken::GilState gil; - - // Remove all references attached to this object - clearReferences(self); - - // Remove the object from parent control - - // Verify if this object has parent - bool hasParent = (self->d->parentInfo && self->d->parentInfo->parent); - - if (self->d->parentInfo) { - // Check for children information and make all invalid if they exists - _destroyParentInfo(self, true); - // If this object has parent then the pyobject can be invalid now, because we remove the last ref after remove from parent - } - - //if !hasParent this object could still alive - if (!hasParent && self->d->containsCppWrapper && !self->d->hasOwnership) { - // Remove extra ref used by c++ object this will case the pyobject destruction - // This can cause the object death - Py_DECREF(reinterpret_cast<PyObject *>(self)); - } - - //Python Object is not destroyed yet - if (cppData && Shiboken::BindingManager::instance().hasWrapper(cppData)) { - // Remove from BindingManager - Shiboken::BindingManager::instance().releaseWrapper(self); - self->d->hasOwnership = false; - - // the cpp object instance was deleted - delete[] self->d->cptr; - self->d->cptr = nullptr; - } - - // After this point the object can be death do not use the self pointer bellow -} - -void removeParent(SbkObject *child, bool giveOwnershipBack, bool keepReference) -{ - ParentInfo *pInfo = child->d->parentInfo; - if (!pInfo || !pInfo->parent) { - if (pInfo && pInfo->hasWrapperRef) { - pInfo->hasWrapperRef = false; - } - return; - } - - ChildrenList &oldBrothers = pInfo->parent->d->parentInfo->children; - // Verify if this child is part of parent list - auto iChild = oldBrothers.find(child); - if (iChild == oldBrothers.end()) - return; - - oldBrothers.erase(iChild); - - pInfo->parent = nullptr; - - // This will keep the wrapper reference, will wait for wrapper destruction to remove that - if (keepReference && - child->d->containsCppWrapper) { - //If have already a extra ref remove this one - if (pInfo->hasWrapperRef) - Py_DECREF(child); - else - pInfo->hasWrapperRef = true; - return; - } - - // Transfer ownership back to Python - child->d->hasOwnership = giveOwnershipBack; - - // Remove parent ref - Py_DECREF(child); -} - -void setParent(PyObject *parent, PyObject *child) -{ - if (!child || child == Py_None || child == parent) - return; - - /* - * setParent is recursive when the child is a native Python sequence, i.e. objects not binded by Shiboken - * like tuple and list. - * - * This "limitation" exists to fix the following problem: A class multiple inherits QObject and QString, - * so if you pass this class to someone that takes the ownership, we CAN'T enter in this if, but hey! QString - * follows the sequence protocol. - */ - if (PySequence_Check(child) && !Object::checkType(child)) { - Shiboken::AutoDecRef seq(PySequence_Fast(child, nullptr)); - for (Py_ssize_t i = 0, max = PySequence_Size(seq); i < max; ++i) - setParent(parent, PySequence_Fast_GET_ITEM(seq.object(), i)); - return; - } - - bool parentIsNull = !parent || parent == Py_None; - auto parent_ = reinterpret_cast<SbkObject *>(parent); - auto child_ = reinterpret_cast<SbkObject *>(child); - - if (!parentIsNull) { - if (!parent_->d->parentInfo) - parent_->d->parentInfo = new ParentInfo; - - // do not re-add a child - if (child_->d->parentInfo && (child_->d->parentInfo->parent == parent_)) - return; - } - - ParentInfo *pInfo = child_->d->parentInfo; - bool hasAnotherParent = pInfo && pInfo->parent && pInfo->parent != parent_; - - //Avoid destroy child during reparent operation - Py_INCREF(child); - - // check if we need to remove this child from the old parent - if (parentIsNull || hasAnotherParent) - removeParent(child_); - - // Add the child to the new parent - pInfo = child_->d->parentInfo; - if (!parentIsNull) { - if (!pInfo) - pInfo = child_->d->parentInfo = new ParentInfo; - - pInfo->parent = parent_; - parent_->d->parentInfo->children.insert(child_); - - // Add Parent ref - Py_INCREF(child_); - - // Remove ownership - child_->d->hasOwnership = false; - } - - // Remove previous safe ref - Py_DECREF(child); -} - -void deallocData(SbkObject *self, bool cleanup) -{ - // Make cleanup if this is not a wrapper otherwise this will be done on wrapper destructor - if(cleanup) { - removeParent(self); - - if (self->d->parentInfo) - _destroyParentInfo(self, true); - - clearReferences(self); - } - - if (self->d->cptr) { - // Remove from BindingManager - Shiboken::BindingManager::instance().releaseWrapper(self); - delete[] self->d->cptr; - self->d->cptr = nullptr; - // delete self->d; PYSIDE-205: wrong! - } - delete self->d; // PYSIDE-205: always delete d. - Py_XDECREF(self->ob_dict); - - // PYSIDE-571: qApp is no longer allocated. - if (PyObject_IS_GC(reinterpret_cast<PyObject *>(self))) - Py_TYPE(self)->tp_free(self); -} - -void setTypeUserData(SbkObject *wrapper, void *userData, DeleteUserDataFunc d_func) -{ - SbkObjectTypePrivate *sotp = PepType_SOTP(Py_TYPE(wrapper)); - if (sotp->user_data) - sotp->d_func(sotp->user_data); - - sotp->d_func = d_func; - sotp->user_data = userData; -} - -void *getTypeUserData(SbkObject *wrapper) -{ - return PepType_SOTP(Py_TYPE(wrapper))->user_data; -} - -static inline bool isNone(const PyObject *o) -{ - return o == nullptr || o == Py_None; -} - -static void removeRefCountKey(SbkObject *self, const char *key) -{ - if (self->d->referredObjects) { - const auto iterPair = self->d->referredObjects->equal_range(key); - if (iterPair.first != iterPair.second) { - decRefPyObjectList(iterPair.first, iterPair.second); - self->d->referredObjects->erase(iterPair.first, iterPair.second); - } - } -} - -void keepReference(SbkObject *self, const char *key, PyObject *referredObject, bool append) -{ - if (isNone(referredObject)) { - removeRefCountKey(self, key); - return; - } - - if (!self->d->referredObjects) { - self->d->referredObjects = - new Shiboken::RefCountMap{RefCountMap::value_type{key, referredObject}}; - Py_INCREF(referredObject); - return; - } - - RefCountMap &refCountMap = *(self->d->referredObjects); - const auto iterPair = refCountMap.equal_range(key); - if (std::any_of(iterPair.first, iterPair.second, - [referredObject](const RefCountMap::value_type &v) { return v.second == referredObject; })) { - return; - } - - if (!append && iterPair.first != iterPair.second) { - decRefPyObjectList(iterPair.first, iterPair.second); - refCountMap.erase(iterPair.first, iterPair.second); - } - - refCountMap.insert(RefCountMap::value_type{key, referredObject}); - Py_INCREF(referredObject); -} - -void removeReference(SbkObject *self, const char *key, PyObject *referredObject) -{ - if (!isNone(referredObject)) - removeRefCountKey(self, key); -} - -void clearReferences(SbkObject *self) -{ - if (!self->d->referredObjects) - return; - - RefCountMap &refCountMap = *(self->d->referredObjects); - for (auto it = refCountMap.begin(), end = refCountMap.end(); it != end; ++it) - Py_DECREF(it->second); - self->d->referredObjects->clear(); -} - -std::string info(SbkObject *self) -{ - std::ostringstream s; - - if (self->d && self->d->cptr) { - std::vector<SbkObjectType *> bases; - if (ObjectType::isUserType(Py_TYPE(self))) - bases = getCppBaseClasses(Py_TYPE(self)); - else - bases.push_back(reinterpret_cast<SbkObjectType *>(Py_TYPE(self))); - - s << "C++ address....... "; - for (size_t i = 0, size = bases.size(); i < size; ++i) { - auto base = reinterpret_cast<PyTypeObject *>(bases[i]); - s << base->tp_name << '/' << self->d->cptr[i] << ' '; - } - s << "\n"; - } - else { - s << "C++ address....... <<Deleted>>\n"; - } - - s << "hasOwnership...... " << bool(self->d->hasOwnership) << "\n" - "containsCppWrapper " << self->d->containsCppWrapper << "\n" - "validCppObject.... " << self->d->validCppObject << "\n" - "wasCreatedByPython " << self->d->cppObjectCreated << "\n"; - - - if (self->d->parentInfo && self->d->parentInfo->parent) { - s << "parent............ "; - Shiboken::AutoDecRef parent(PyObject_Str(reinterpret_cast<PyObject *>(self->d->parentInfo->parent))); - s << String::toCString(parent) << "\n"; - } - - if (self->d->parentInfo && !self->d->parentInfo->children.empty()) { - s << "children.......... "; - for (SbkObject *sbkChild : self->d->parentInfo->children) { - Shiboken::AutoDecRef child(PyObject_Str(reinterpret_cast<PyObject *>(sbkChild))); - s << String::toCString(child) << ' '; - } - s << '\n'; - } - - if (self->d->referredObjects && !self->d->referredObjects->empty()) { - 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) { - if (!lastKey.empty()) - s << " "; - s << '"' << it->first << "\" => "; - lastKey = it->first; - } - Shiboken::AutoDecRef obj(PyObject_Str(it->second)); - s << String::toCString(obj) << ' '; - } - s << '\n'; - } - return s.str(); -} - -} // namespace Object - -} // namespace Shiboken diff --git a/sources/shiboken2/libshiboken/basewrapper.h b/sources/shiboken2/libshiboken/basewrapper.h deleted file mode 100644 index 31083522b..000000000 --- a/sources/shiboken2/libshiboken/basewrapper.h +++ /dev/null @@ -1,479 +0,0 @@ -/**************************************************************************** -** -** 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$ -** -****************************************************************************/ - -#ifndef BASEWRAPPER_H -#define BASEWRAPPER_H - -#include "sbkpython.h" -#include "shibokenmacros.h" - -#include <vector> -#include <string> - -extern "C" -{ - -struct SbkConverter; -struct SbkObjectPrivate; - -/// Base Python object for all the wrapped C++ classes. -struct LIBSHIBOKEN_API SbkObject -{ - PyObject_HEAD - /// Instance dictionary. - PyObject *ob_dict; - /// List of weak references - PyObject *weakreflist; - SbkObjectPrivate *d; -}; - - -/// PYSIDE-939: A general replacement for object_dealloc. -LIBSHIBOKEN_API void Sbk_object_dealloc(PyObject *self); - -/// Dealloc the python object \p pyObj and the C++ object represented by it. -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 *); - -/** - * 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 *); - -// Used in userdata dealloc function -typedef void (*DeleteUserDataFunc)(void *); - -typedef void (*ObjectDestructor)(void *); - -typedef void (*SubTypeInitHook)(SbkObjectType *, PyObject *, PyObject *); - -// PYSIDE-1019: Set the function to select the current feature. -typedef PyObject *(*SelectableFeatureHook)(PyTypeObject *); -LIBSHIBOKEN_API void initSelectableFeature(SelectableFeatureHook 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-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); - - -extern LIBSHIBOKEN_API PyTypeObject *SbkObjectType_TypeF(void); -extern LIBSHIBOKEN_API SbkObjectType *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 *); -// the special case of a switchable singleton -LIBSHIBOKEN_API PyObject *SbkQAppTpNew(PyTypeObject *subtype, PyObject *args, PyObject *kwds); - -/** - * 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 - * 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); - -} // extern "C" - -namespace Shiboken -{ - -/** -* Init shiboken library. -*/ -LIBSHIBOKEN_API void init(); - - -/// Delete the class T allocated on \p cptr. -template<typename T> -void callCppDestructor(void *cptr) -{ - delete reinterpret_cast<T *>(cptr); -} - -// setErrorAboutWrongArguments now gets overload info from the signature module. -LIBSHIBOKEN_API void setErrorAboutWrongArguments(PyObject *args, const char *funcName); - -namespace ObjectType { - -/** -* Returns true if the object is an instance of a type created by the Shiboken generator. -*/ -LIBSHIBOKEN_API bool checkType(PyTypeObject *pyObj); - -/** -* Returns true if this object is an instance of an user defined type derived from an Shiboken type. -*/ -LIBSHIBOKEN_API bool isUserType(PyTypeObject *pyObj); - -/** -* Returns true if the constructor of \p ctorType can be called for a instance of type \p myType. -* \note This function set a python error when returning false. -*/ -LIBSHIBOKEN_API bool canCallConstructor(PyTypeObject *myType, PyTypeObject *ctorType); - -/** - * Tells if the \p type represents an object of a class with multiple inheritance in C++. - * When this occurs, the C++ pointer held by the Python wrapper will need to be cast when - * passed as a parameter that expects a type of its ancestry. - * \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); -/** - * 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); -/// 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 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 setDestructorFunction(SbkObjectType *self, ObjectDestructor func); - -LIBSHIBOKEN_API void initPrivateData(SbkObjectType *self); - -enum WrapperFlags -{ - InnerClass = 0x1, - DeleteInMainThread = 0x2 -}; - -/** - * 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. - * \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. - * \param type The new type to be initialized and added to the module. - * \param cppObjDtor Memory deallocation function for the C++ object held by \p type. - * Should not be used if the underlying C++ class has a private destructor. - * \param baseType Base type from whom the new \p type inherits. - * \param baseTypes Other base types from whom the new \p type inherits. - * \param isInnerClass Tells if the new \p type is an inner class (the default is that it isn't). - * If false then the \p enclosingObject is a module, otherwise it is another - * 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); - -/** - * Set the subtype init hook for a type. - * - * This hook will be invoked every time the user creates a sub-type inherited from a Shiboken based type. - * 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); - -/** - * 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); - -/** - * 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 { - -/** - * Returns a string with information about the internal state of the instance object, useful for debug purposes. - */ -LIBSHIBOKEN_API std::string info(SbkObject *self); - -/** -* Returns true if the object is an instance of a type created by the Shiboken generator. -*/ -LIBSHIBOKEN_API bool checkType(PyObject *pyObj); - -/** - * Returns true if this object type is an instance of an user defined type derived from an Shiboken type. - * \see Shiboken::ObjectType::isUserType - */ -LIBSHIBOKEN_API bool isUserType(PyObject *pyObj); - -/** - * Generic function used to make ObjectType hashable, the C++ pointer is used as hash value. - */ -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); - -/** - * Bind a C++ object to Python. - * \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++ - * object, in any case you must provide \p instanceType, it'll be used as search starting point - * 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, - void *cptr, - bool hasOwnership = true, - bool isExactType = false, - const char *typeName = nullptr); - -/** - * Changes the valid flag of a PyObject, invalid objects will raise an exception when someone tries to access it. - */ -LIBSHIBOKEN_API void setValidCpp(SbkObject *pyObj, bool value); -/** - * Tells shiboken the Python object \p pyObj has a C++ wrapper used to intercept virtual method calls. - */ -LIBSHIBOKEN_API void setHasCppWrapper(SbkObject *pyObj, bool value); -/** - * Return true if the Python object \p pyObj has a C++ wrapper used to intercept virtual method calls. - */ -LIBSHIBOKEN_API bool hasCppWrapper(SbkObject *pyObj); - -/** - * Return true if the Python object was created by Python, false otherwise. - * \note This function was added to libshiboken only to be used by shiboken.wasCreatedByPython() - */ -LIBSHIBOKEN_API bool wasCreatedByPython(SbkObject *pyObj); - -/** - * Call the C++ object destructor and invalidates the Python object. - * \note This function was added to libshiboken only to be used by shiboken.delete() - */ -LIBSHIBOKEN_API void callCppDestructors(SbkObject *pyObj); - -/** - * Return true if the Python is responsible for deleting the underlying C++ object. - */ -LIBSHIBOKEN_API bool hasOwnership(SbkObject *pyObj); - -/** - * Sets python as responsible to delete the underlying C++ object. - * \note You this overload only when the PyObject can be a sequence and you want to - * call this function for every item in the sequence. - * \see getOwnership(SbkObject *) - */ -LIBSHIBOKEN_API void getOwnership(PyObject *pyObj); - -/** - * Sets python as responsible to delete the underlying C++ object. - */ -LIBSHIBOKEN_API void getOwnership(SbkObject *pyObj); - -/** - * Release the ownership, so Python will not delete the underlying C++ object. - * \note You this overload only when the PyObject can be a sequence and you want to - * call this function for every item in the sequence. - * \see releaseOwnership(SbkObject *) - */ -LIBSHIBOKEN_API void releaseOwnership(PyObject *pyObj); -/** - * Release the ownership, so Python will not delete the underlying C++ object. - */ -LIBSHIBOKEN_API void releaseOwnership(SbkObject *pyObj); - -/** - * Get the C++ pointer of type \p desiredType from a Python object. - */ -LIBSHIBOKEN_API void *cppPointer(SbkObject *pyObj, PyTypeObject *desiredType); - -/** - * Return a list with all C++ pointers held from a Python object. - * \note This function was added to libshiboken only to be used by shiboken.getCppPointer() - */ -LIBSHIBOKEN_API std::vector<void *>cppPointers(SbkObject *pyObj); - -/** - * Set the C++ pointer of type \p desiredType of a Python object. - */ -LIBSHIBOKEN_API bool setCppPointer(SbkObject *sbkObj, PyTypeObject *desiredType, void *cptr); - -/** - * Returns false and sets a Python RuntimeError if the Python wrapper is not marked as valid. - */ -LIBSHIBOKEN_API bool isValid(PyObject *pyObj); - -/** - * Returns false if the Python wrapper is not marked as valid. - * \param pyObj the object. - * \param throwPyError sets a Python RuntimeError when the object isn't valid. - */ -LIBSHIBOKEN_API bool isValid(SbkObject *pyObj, bool throwPyError = true); - -/** - * Returns false if the Python wrapper is not marked as valid. - * \param pyObj the object. - * \param throwPyError sets a Python RuntimeError when the object isn't valid. - */ -LIBSHIBOKEN_API bool isValid(PyObject *pyObj, bool throwPyError); - -/** -* Set the parent of \p child to \p parent. -* When an object dies, all their children, grandchildren, etc, are tagged as invalid. -* \param parent the parent object, if null, the child will have no parents. -* \param child the child. -*/ -LIBSHIBOKEN_API void setParent(PyObject *parent, PyObject *child); - -/** -* Remove this child from their parent, if any. -* \param child the child. -*/ -LIBSHIBOKEN_API void removeParent(SbkObject *child, bool giveOwnershipBack = true, bool keepReferenc = false); - -/** - * Mark the object as invalid - */ -LIBSHIBOKEN_API void invalidate(SbkObject *self); - -/** - * Help function can be used to invalidate a sequence of object - **/ -LIBSHIBOKEN_API void invalidate(PyObject *pyobj); - -/** - * Make the object valid again - */ -LIBSHIBOKEN_API void makeValid(SbkObject *self); - -/** - * Destroy any data in Shiboken structure and c++ pointer if the pyboject has the ownership - */ -LIBSHIBOKEN_API void destroy(SbkObject *self, void *cppData); - -/** - * Set user data on type of \p wrapper. - * \param wrapper instance object, the user data will be set on his type - * \param userData the user data - * \param d_func a function used to delete the user data - */ -LIBSHIBOKEN_API void setTypeUserData(SbkObject *wrapper, void *userData, DeleteUserDataFunc d_func); -/** - * Get the user data previously set by Shiboken::Object::setTypeUserData - */ -LIBSHIBOKEN_API void *getTypeUserData(SbkObject *wrapper); - -/** - * Increments the reference count of the referred Python object. - * A previous Python object in the same position identified by the 'key' parameter - * will have its reference counter decremented automatically when replaced. - * All the kept references should be decremented when the Python wrapper indicated by - * 'self' dies. - * No checking is done for any of the passed arguments, since it is meant to be used - * by generated code it is supposed that the generator is correct. - * \param self the wrapper instance that keeps references to other objects. - * \param key a key that identifies the C++ method signature and argument where the referred Object came from. - * \param referredObject the object whose reference is used by the self object. - */ -LIBSHIBOKEN_API void keepReference(SbkObject *self, const char *key, PyObject *referredObject, bool append = false); - -/** - * Removes any reference previously added by keepReference function - * \param self the wrapper instance that keeps references to other objects. - * \param key a key that identifies the C++ method signature and argument from where the referred Object came. - * \param referredObject the object whose reference is used by the self object. - */ -LIBSHIBOKEN_API void removeReference(SbkObject *self, const char *key, PyObject *referredObject); - -} // namespace Object - -} // namespace Shiboken - -#endif // BASEWRAPPER_H diff --git a/sources/shiboken2/libshiboken/basewrapper_p.h b/sources/shiboken2/libshiboken/basewrapper_p.h deleted file mode 100644 index 64f7941b7..000000000 --- a/sources/shiboken2/libshiboken/basewrapper_p.h +++ /dev/null @@ -1,292 +0,0 @@ -/**************************************************************************** -** -** Copyright (C) 2016 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$ -** -****************************************************************************/ - -#ifndef BASEWRAPPER_P_H -#define BASEWRAPPER_P_H - -#include "sbkpython.h" -#include "basewrapper.h" - -#include <unordered_map> -#include <set> -#include <string> -#include <vector> - -struct SbkObject; -struct SbkObjectType; -struct SbkConverter; - -namespace Shiboken -{ -/** - * This mapping associates a method and argument of an wrapper object with the wrapper of - * said argument when it needs the binding to help manage its reference count. - */ -using RefCountMap = std::unordered_multimap<std::string, PyObject *> ; - -/// Linked list of SbkBaseWrapper pointers -using ChildrenList = std::set<SbkObject *>; - -/// Structure used to store information about object parent and children. -struct ParentInfo -{ - /// Default ctor. - ParentInfo() : parent(nullptr), hasWrapperRef(false) {} - /// Pointer to parent object. - SbkObject *parent; - /// List of object children. - ChildrenList children; - /// has internal ref - bool hasWrapperRef; -}; - -} // namespace Shiboken - -extern "C" -{ - -/** - * \internal - * Private data for SbkBaseWrapper - */ -struct SbkObjectPrivate -{ - /// Pointer to the C++ class. - void ** cptr; - /// True when Python is responsible for freeing the used memory. - unsigned int hasOwnership : 1; - /// This is true when the C++ class of the wrapped object has a virtual destructor AND was created by Python. - unsigned int containsCppWrapper : 1; - /// Marked as false when the object is lost to C++ and the binding can not know if it was deleted or not. - unsigned int validCppObject : 1; - /// Marked as true when the object constructor was called - unsigned int cppObjectCreated : 1; - /// Information about the object parents and children, may be null. - Shiboken::ParentInfo *parentInfo; - /// Manage reference count of objects that are referred to but not owned from. - Shiboken::RefCountMap *referredObjects; - - ~SbkObjectPrivate() - { - delete parentInfo; - parentInfo = nullptr; - delete referredObjects; - referredObjects = nullptr; - } -}; - -// TODO-CONVERTERS: to be deprecated/removed -/// The type behaviour was not defined yet -#define BEHAVIOUR_UNDEFINED 0 -/// The type is a value type -#define BEHAVIOUR_VALUETYPE 1 -/// The type is an object type -#define BEHAVIOUR_OBJECTTYPE 2 - -struct SbkObjectTypePrivate -{ - SbkConverter *converter; - int *mi_offsets; - MultipleInheritanceInitFunction mi_init; - - /// Special cast function, null if this class doesn't have multiple inheritance. - SpecialCastFunction mi_specialcast; - TypeDiscoveryFuncV2 type_discovery; - /// Pointer to a function responsible for deletion of the C++ instance calling the proper destructor. - ObjectDestructor cpp_dtor; - /// PYSIDE-1019: Caching the current select Id - unsigned int pyside_reserved_bits : 8; // MSVC has bug with the sign bit! - /// True if this type holds two or more C++ instances, e.g.: a Python class which inherits from two C++ classes. - unsigned int is_multicpp : 1; - /// True if this type was defined by the user. - unsigned int is_user_type : 1; - /// Tells is the type is a value type or an object-type, see BEHAVIOUR_ *constants. - // TODO-CONVERTERS: to be deprecated/removed - unsigned int type_behaviour : 2; - unsigned int delete_in_main_thread : 1; - /// C++ name - char *original_name; - /// Type user data - void *user_data; - DeleteUserDataFunc d_func; - void (*subtype_init)(SbkObjectType *, PyObject *, PyObject *); - const char **propertyStrings; -}; - - -} // extern "C" - -namespace Shiboken -{ - -/** - * \internal - * Data required to invoke a C++ destructor - */ -struct DestructorEntry -{ - ObjectDestructor destructor; - void *cppInstance; -}; - -/** - * Utility function used to transform a PyObject that implements sequence protocol into a std::list. - **/ -std::vector<SbkObject *> splitPyObject(PyObject *pyObj); - -/** -* Visitor class used by walkOnClassHierarchy function. -*/ -class HierarchyVisitor -{ -public: - HierarchyVisitor(const HierarchyVisitor &) = delete; - HierarchyVisitor(HierarchyVisitor &&) = delete; - HierarchyVisitor &operator=(const HierarchyVisitor &) = delete; - HierarchyVisitor &operator=(HierarchyVisitor &&) = delete; - - HierarchyVisitor(); - virtual ~HierarchyVisitor(); - - virtual bool visit(SbkObjectType *node) = 0; // return true to terminate -}; - -class BaseCountVisitor : public HierarchyVisitor -{ -public: - bool visit(SbkObjectType *) override; - - int count() const { return m_count; } - -private: - int m_count = 0; -}; - -class BaseAccumulatorVisitor : public HierarchyVisitor -{ -public: - using Result = std::vector<SbkObjectType *>; - - bool visit(SbkObjectType *node) override; - - Result bases() const { return m_bases; } - -private: - Result m_bases; -}; - -class GetIndexVisitor : public HierarchyVisitor -{ -public: - explicit GetIndexVisitor(PyTypeObject *desiredType) : m_desiredType(desiredType) {} - - bool visit(SbkObjectType *node) override; - - int index() const { return m_index; } - -private: - int m_index = -1; - PyTypeObject *m_desiredType; -}; - -/// Collect destructors and C++ instances of each C++ object held by a Python -/// object -class DtorAccumulatorVisitor : public HierarchyVisitor -{ -public: - explicit DtorAccumulatorVisitor(SbkObject *pyObj) : m_pyObject(pyObj) {} - - bool visit(SbkObjectType *node) override; - - using DestructorEntries = std::vector<DestructorEntry>; - - const DestructorEntries &entries() const { return m_entries; } - -private: - DestructorEntries m_entries; - SbkObject *m_pyObject; -}; - -/// \internal Internal function used to walk on classes inheritance trees. -/** -* Walk on class hierarchy using a DFS algorithm. -* For each pure Shiboken type found, HiearchyVisitor::visit is called and the algorithm consider -* all children of this type as visited. -*/ -bool walkThroughClassHierarchy(PyTypeObject *currentType, HierarchyVisitor *visitor); - -inline int getTypeIndexOnHierarchy(PyTypeObject *baseType, PyTypeObject *desiredType) -{ - GetIndexVisitor visitor(desiredType); - walkThroughClassHierarchy(baseType, &visitor); - return visitor.index(); -} - -inline int getNumberOfCppBaseClasses(PyTypeObject *baseType) -{ - BaseCountVisitor visitor; - walkThroughClassHierarchy(baseType, &visitor); - return visitor.count(); -} - -inline std::vector<SbkObjectType *> getCppBaseClasses(PyTypeObject *baseType) -{ - BaseAccumulatorVisitor visitor; - walkThroughClassHierarchy(baseType, &visitor); - return visitor.bases(); -} - -namespace Object -{ -/** -* Decrements the reference counters of every object referred by self. -* \param self the wrapper instance that keeps references to other objects. -*/ -void clearReferences(SbkObject *self); - -/** - * Destroy internal data - **/ -void deallocData(SbkObject *self, bool doCleanup); - -} // namespace Object - -} // namespace Shiboken - -#endif diff --git a/sources/shiboken2/libshiboken/bindingmanager.cpp b/sources/shiboken2/libshiboken/bindingmanager.cpp deleted file mode 100644 index 78c03556c..000000000 --- a/sources/shiboken2/libshiboken/bindingmanager.cpp +++ /dev/null @@ -1,374 +0,0 @@ -/**************************************************************************** -** -** Copyright (C) 2016 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$ -** -****************************************************************************/ - -#include "autodecref.h" -#include "basewrapper.h" -#include "basewrapper_p.h" -#include "bindingmanager.h" -#include "sbkdbg.h" -#include "gilstate.h" -#include "sbkstring.h" -#include "sbkstaticstrings.h" -#include "debugfreehook.h" - -#include <cstddef> -#include <fstream> -#include <unordered_map> - -namespace Shiboken -{ - -using WrapperMap = std::unordered_map<const void *, SbkObject *>; - -class Graph -{ -public: - using NodeList = std::vector<SbkObjectType *>; - using Edges = std::unordered_map<SbkObjectType *, NodeList>; - - Edges m_edges; - - Graph() = default; - - void addEdge(SbkObjectType *from, SbkObjectType *to) - { - m_edges[from].push_back(to); - } - -#ifndef NDEBUG - void dumpDotGraph() - { - std::ofstream file("/tmp/shiboken_graph.dot"); - - file << "digraph D {\n"; - - for (auto i = m_edges.begin(), end = m_edges.end(); i != end; ++i) { - auto node1 = reinterpret_cast<const PyTypeObject *>(i->first); - const NodeList &nodeList = i->second; - for (const SbkObjectType *o : nodeList) { - auto node2 = reinterpret_cast<const PyTypeObject *>(o); - file << '"' << node2->tp_name << "\" -> \"" - << node1->tp_name << "\"\n"; - } - } - file << "}\n"; - } -#endif - - SbkObjectType *identifyType(void **cptr, SbkObjectType *type, SbkObjectType *baseType) const - { - auto edgesIt = m_edges.find(type); - if (edgesIt != m_edges.end()) { - const NodeList &adjNodes = m_edges.find(type)->second; - for (SbkObjectType *node : adjNodes) { - SbkObjectType *newType = identifyType(cptr, node, baseType); - if (newType) - return newType; - } - } - void *typeFound = nullptr; - if (PepType_SOTP(type) && PepType_SOTP(type)->type_discovery) { - typeFound = PepType_SOTP(type)->type_discovery(*cptr, baseType); - } - if (typeFound) { - // This "typeFound != type" is needed for backwards compatibility with old modules using a newer version of - // libshiboken because old versions of type_discovery function used to return a SbkObjectType *instead of - // a possible variation of the C++ instance pointer (*cptr). - if (typeFound != type) - *cptr = typeFound; - return type; - } - return nullptr; - } -}; - - -#ifndef NDEBUG -static void showWrapperMap(const WrapperMap &wrapperMap) -{ - if (Py_VerboseFlag > 0) { - fprintf(stderr, "-------------------------------\n"); - fprintf(stderr, "WrapperMap: %p (size: %d)\n", &wrapperMap, (int) wrapperMap.size()); - for (auto it = wrapperMap.begin(), end = wrapperMap.end(); it != end; ++it) { - const SbkObject *sbkObj = it->second; - fprintf(stderr, "key: %p, value: %p (%s, refcnt: %d)\n", it->first, - static_cast<const void *>(sbkObj), - (Py_TYPE(sbkObj))->tp_name, - int(reinterpret_cast<const PyObject *>(sbkObj)->ob_refcnt)); - } - fprintf(stderr, "-------------------------------\n"); - } -} -#endif - -struct BindingManager::BindingManagerPrivate { - using DestructorEntries = std::vector<DestructorEntry>; - - WrapperMap wrapperMapper; - Graph classHierarchy; - DestructorEntries deleteInMainThread; - bool destroying; - - BindingManagerPrivate() : destroying(false) {} - bool releaseWrapper(void *cptr, SbkObject *wrapper); - void assignWrapper(SbkObject *wrapper, const void *cptr); - -}; - -bool BindingManager::BindingManagerPrivate::releaseWrapper(void *cptr, SbkObject *wrapper) -{ - // The wrapper argument is checked to ensure that the correct wrapper is released. - // Returns true if the correct wrapper is found and released. - // If wrapper argument is NULL, no such check is performed. - auto iter = wrapperMapper.find(cptr); - if (iter != wrapperMapper.end() && (wrapper == nullptr || iter->second == wrapper)) { - wrapperMapper.erase(iter); - return true; - } - return false; -} - -void BindingManager::BindingManagerPrivate::assignWrapper(SbkObject *wrapper, const void *cptr) -{ - assert(cptr); - auto iter = wrapperMapper.find(cptr); - if (iter == wrapperMapper.end()) - wrapperMapper.insert(std::make_pair(cptr, wrapper)); -} - -BindingManager::BindingManager() -{ - m_d = new BindingManager::BindingManagerPrivate; - -#ifdef SHIBOKEN_INSTALL_FREE_DEBUG_HOOK - debugInstallFreeHook(); -#endif -} - -BindingManager::~BindingManager() -{ -#ifdef SHIBOKEN_INSTALL_FREE_DEBUG_HOOK - debugRemoveFreeHook(); -#endif -#ifndef NDEBUG - showWrapperMap(m_d->wrapperMapper); -#endif - /* Cleanup hanging references. We just invalidate them as when - * the BindingManager is being destroyed the interpreter is alredy - * shutting down. */ - if (Py_IsInitialized()) { // ensure the interpreter is still valid - while (!m_d->wrapperMapper.empty()) { - Object::destroy(m_d->wrapperMapper.begin()->second, const_cast<void *>(m_d->wrapperMapper.begin()->first)); - } - assert(m_d->wrapperMapper.empty()); - } - delete m_d; -} - -BindingManager &BindingManager::instance() { - static BindingManager singleton; - return singleton; -} - -bool BindingManager::hasWrapper(const void *cptr) -{ - return m_d->wrapperMapper.find(cptr) != m_d->wrapperMapper.end(); -} - -void BindingManager::registerWrapper(SbkObject *pyObj, void *cptr) -{ - auto instanceType = reinterpret_cast<SbkObjectType *>(Py_TYPE(pyObj)); - SbkObjectTypePrivate *d = PepType_SOTP(instanceType); - - if (!d) - return; - - if (d->mi_init && !d->mi_offsets) - d->mi_offsets = d->mi_init(cptr); - m_d->assignWrapper(pyObj, cptr); - if (d->mi_offsets) { - int *offset = d->mi_offsets; - while (*offset != -1) { - if (*offset > 0) - m_d->assignWrapper(pyObj, reinterpret_cast<void *>(reinterpret_cast<uintptr_t>(cptr) + *offset)); - offset++; - } - } -} - -void BindingManager::releaseWrapper(SbkObject *sbkObj) -{ - auto sbkType = reinterpret_cast<SbkObjectType *>(Py_TYPE(sbkObj)); - SbkObjectTypePrivate *d = PepType_SOTP(sbkType); - int numBases = ((d && d->is_multicpp) ? getNumberOfCppBaseClasses(Py_TYPE(sbkObj)) : 1); - - void ** cptrs = reinterpret_cast<SbkObject *>(sbkObj)->d->cptr; - for (int i = 0; i < numBases; ++i) { - auto *cptr = reinterpret_cast<unsigned char *>(cptrs[i]); - m_d->releaseWrapper(cptr, sbkObj); - if (d && d->mi_offsets) { - int *offset = d->mi_offsets; - while (*offset != -1) { - if (*offset > 0) - m_d->releaseWrapper(reinterpret_cast<void *>(reinterpret_cast<uintptr_t>(cptr) + *offset), sbkObj); - offset++; - } - } - } - sbkObj->d->validCppObject = false; -} - -void BindingManager::runDeletionInMainThread() -{ - for (const DestructorEntry &e : m_d->deleteInMainThread) - e.destructor(e.cppInstance); - m_d->deleteInMainThread.clear(); -} - -void BindingManager::addToDeletionInMainThread(const DestructorEntry &e) -{ - m_d->deleteInMainThread.push_back(e); -} - -SbkObject *BindingManager::retrieveWrapper(const void *cptr) -{ - auto iter = m_d->wrapperMapper.find(cptr); - if (iter == m_d->wrapperMapper.end()) - return nullptr; - return iter->second; -} - -static inline int currentSelectId(PyTypeObject *type) -{ - int sel = SbkObjectType_GetReserved(type); - // This could theoretically be -1 if used too early. - assert(sel >= 0); - return sel; -} - -PyObject *BindingManager::getOverride(const void *cptr, - PyObject *nameCache[], - const char *methodName) -{ - SbkObject *wrapper = retrieveWrapper(cptr); - // The refcount can be 0 if the object is dieing and someone called - // a virtual method from the destructor - if (!wrapper || reinterpret_cast<const PyObject *>(wrapper)->ob_refcnt == 0) - return nullptr; - - int flag = currentSelectId(Py_TYPE(wrapper)); - int propFlag = isdigit(methodName[0]) ? methodName[0] - '0' : 0; - if ((flag & 0x02) != 0 && (propFlag & 3) != 0) { - // PYSIDE-1019: Handle overriding with properties. - // They cannot be overridden (make that sure by the metaclass). - return nullptr; - } - PyObject *pyMethodName = nameCache[(flag & 1) != 0]; // borrowed - if (pyMethodName == nullptr) { - if (propFlag) - methodName += 2; // skip the propFlag and ':' - pyMethodName = Shiboken::String::getSnakeCaseName(methodName, flag); - nameCache[(flag & 1) != 0] = pyMethodName; - } - - if (wrapper->ob_dict) { - PyObject *method = PyDict_GetItem(wrapper->ob_dict, pyMethodName); - if (method) { - Py_INCREF(method); - return method; - } - } - - PyObject *method = PyObject_GetAttr(reinterpret_cast<PyObject *>(wrapper), pyMethodName); - - if (method && PyMethod_Check(method) - && PyMethod_GET_SELF(method) == reinterpret_cast<PyObject *>(wrapper)) { - PyObject *defaultMethod; - PyObject *mro = Py_TYPE(wrapper)->tp_mro; - - int size = PyTuple_GET_SIZE(mro); - // The first class in the mro (index 0) is the class being checked and it should not be tested. - // The last class in the mro (size - 1) is the base Python object class which should not be tested also. - for (int idx = 1; idx < size - 1; ++idx) { - auto *parent = reinterpret_cast<PyTypeObject *>(PyTuple_GET_ITEM(mro, idx)); - if (parent->tp_dict) { - defaultMethod = PyDict_GetItem(parent->tp_dict, pyMethodName); - if (defaultMethod && PyMethod_GET_FUNCTION(method) != defaultMethod) - return method; - } - } - } else { - Py_XDECREF(method); - } - return nullptr; -} - -void BindingManager::addClassInheritance(SbkObjectType *parent, SbkObjectType *child) -{ - m_d->classHierarchy.addEdge(parent, child); -} - -SbkObjectType *BindingManager::resolveType(void **cptr, SbkObjectType *type) -{ - SbkObjectType *identifiedType = m_d->classHierarchy.identifyType(cptr, type, type); - return identifiedType ? identifiedType : type; -} - -std::set<PyObject *> BindingManager::getAllPyObjects() -{ - std::set<PyObject *> pyObjects; - const WrapperMap &wrappersMap = m_d->wrapperMapper; - auto it = wrappersMap.begin(); - for (; it != wrappersMap.end(); ++it) - pyObjects.insert(reinterpret_cast<PyObject *>(it->second)); - - return pyObjects; -} - -void BindingManager::visitAllPyObjects(ObjectVisitor visitor, void *data) -{ - WrapperMap copy = m_d->wrapperMapper; - for (auto it = copy.begin(); it != copy.end(); ++it) { - if (hasWrapper(it->first)) - visitor(it->second, data); - } -} - -} // namespace Shiboken - diff --git a/sources/shiboken2/libshiboken/bindingmanager.h b/sources/shiboken2/libshiboken/bindingmanager.h deleted file mode 100644 index 5b2246685..000000000 --- a/sources/shiboken2/libshiboken/bindingmanager.h +++ /dev/null @@ -1,110 +0,0 @@ -/**************************************************************************** -** -** Copyright (C) 2016 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$ -** -****************************************************************************/ - -#ifndef BINDINGMANAGER_H -#define BINDINGMANAGER_H - -#include "sbkpython.h" -#include <set> -#include "shibokenmacros.h" - -struct SbkObject; -struct SbkObjectType; - -namespace Shiboken -{ - -struct DestructorEntry; - -typedef void (*ObjectVisitor)(SbkObject *, void *); - -class LIBSHIBOKEN_API BindingManager -{ -public: - BindingManager(const BindingManager &) = delete; - BindingManager(BindingManager &&) = delete; - BindingManager &operator=(const BindingManager &) = delete; - BindingManager &operator=(BindingManager &&) = delete; - - static BindingManager &instance(); - - bool hasWrapper(const void *cptr); - - void registerWrapper(SbkObject *pyObj, void *cptr); - void releaseWrapper(SbkObject *wrapper); - - void runDeletionInMainThread(); - void addToDeletionInMainThread(const DestructorEntry &); - - SbkObject *retrieveWrapper(const void *cptr); - PyObject *getOverride(const void *cptr, PyObject *nameCache[], const char *methodName); - - void addClassInheritance(SbkObjectType *parent, SbkObjectType *child); - /** - * Try to find the correct type of *cptr knowing that it's at least of type \p type. - * In case of multiple inheritance this function may change the contents of cptr. - * \param cptr a pointer to a pointer to the instance of type \p type - * \param type type of *cptr - * \warning This function is slow, use it only as last resort. - */ - SbkObjectType *resolveType(void **cptr, SbkObjectType *type); - - std::set<PyObject *> getAllPyObjects(); - - /** - * Calls the function \p visitor for each object registered on binding manager. - * \note As various C++ pointers can point to the same PyObject due to multiple inheritance - * a PyObject can be called more than one time for each PyObject. - * \param visitor function called for each object. - * \param data user data passed as second argument to the visitor function. - */ - void visitAllPyObjects(ObjectVisitor visitor, void *data); - -private: - ~BindingManager(); - BindingManager(); - - struct BindingManagerPrivate; - BindingManagerPrivate *m_d; -}; - -} // namespace Shiboken - -#endif // BINDINGMANAGER_H - diff --git a/sources/shiboken2/libshiboken/bufferprocs_py37.cpp b/sources/shiboken2/libshiboken/bufferprocs_py37.cpp deleted file mode 100644 index da6bb00a3..000000000 --- a/sources/shiboken2/libshiboken/bufferprocs_py37.cpp +++ /dev/null @@ -1,396 +0,0 @@ -/**************************************************************************** -** -** Copyright (C) 2018 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$ -** -****************************************************************************/ - -/***************************************************************************** - * - * Copied from abstract.c - * - * Py_buffer has been replaced by Pep_buffer - * - */ - -#ifdef Py_LIMITED_API - -#include "sbkpython.h" -/* Buffer C-API for Python 3.0 */ - -int -PyObject_GetBuffer(PyObject *obj, Pep_buffer *view, int flags) -{ - PyBufferProcs *pb = PepType_AS_BUFFER(Py_TYPE(obj)); - - if (pb == NULL || pb->bf_getbuffer == NULL) { - PyErr_Format(PyExc_TypeError, - "a bytes-like object is required, not '%.100s'", - Py_TYPE(obj)->tp_name); - return -1; - } - return (*pb->bf_getbuffer)(obj, view, flags); -} - -static int -_IsFortranContiguous(const Pep_buffer *view) -{ - Py_ssize_t sd, dim; - int i; - - /* 1) len = product(shape) * itemsize - 2) itemsize > 0 - 3) len = 0 <==> exists i: shape[i] = 0 */ - if (view->len == 0) return 1; - if (view->strides == NULL) { /* C-contiguous by definition */ - /* Trivially F-contiguous */ - if (view->ndim <= 1) return 1; - - /* ndim > 1 implies shape != NULL */ - assert(view->shape != NULL); - - /* Effectively 1-d */ - sd = 0; - for (i=0; i<view->ndim; i++) { - if (view->shape[i] > 1) sd += 1; - } - return sd <= 1; - } - - /* strides != NULL implies both of these */ - assert(view->ndim > 0); - assert(view->shape != NULL); - - sd = view->itemsize; - for (i=0; i<view->ndim; i++) { - dim = view->shape[i]; - if (dim > 1 && view->strides[i] != sd) { - return 0; - } - sd *= dim; - } - return 1; -} - -static int -_IsCContiguous(const Pep_buffer *view) -{ - Py_ssize_t sd, dim; - int i; - - /* 1) len = product(shape) * itemsize - 2) itemsize > 0 - 3) len = 0 <==> exists i: shape[i] = 0 */ - if (view->len == 0) return 1; - if (view->strides == NULL) return 1; /* C-contiguous by definition */ - - /* strides != NULL implies both of these */ - assert(view->ndim > 0); - assert(view->shape != NULL); - - sd = view->itemsize; - for (i=view->ndim-1; i>=0; i--) { - dim = view->shape[i]; - if (dim > 1 && view->strides[i] != sd) { - return 0; - } - sd *= dim; - } - return 1; -} - -int -PyBuffer_IsContiguous(const Pep_buffer *view, char order) -{ - - if (view->suboffsets != NULL) return 0; - - if (order == 'C') - return _IsCContiguous(view); - else if (order == 'F') - return _IsFortranContiguous(view); - else if (order == 'A') - return (_IsCContiguous(view) || _IsFortranContiguous(view)); - return 0; -} - - -void * -PyBuffer_GetPointer(Pep_buffer *view, Py_ssize_t *indices) -{ - int i; - auto pointer = reinterpret_cast<char *>(view->buf); - for (i = 0; i < view->ndim; i++) { - pointer += view->strides[i]*indices[i]; - if ((view->suboffsets != NULL) && (view->suboffsets[i] >= 0)) { - pointer = *reinterpret_cast<char **>(pointer) + view->suboffsets[i]; - } - } - return pointer; -} - - -void -_Py_add_one_to_index_F(int nd, Py_ssize_t *index, const Py_ssize_t *shape) -{ - int k; - - for (k=0; k<nd; k++) { - if (index[k] < shape[k]-1) { - index[k]++; - break; - } - else { - index[k] = 0; - } - } -} - -void -_Py_add_one_to_index_C(int nd, Py_ssize_t *index, const Py_ssize_t *shape) -{ - int k; - - for (k=nd-1; k>=0; k--) { - if (index[k] < shape[k]-1) { - index[k]++; - break; - } - else { - index[k] = 0; - } - } -} - -int -PyBuffer_FromContiguous(Pep_buffer *view, void *buf, Py_ssize_t len, char fort) -{ - int k; - void (*addone)(int, Py_ssize_t *, const Py_ssize_t *); - Py_ssize_t *indices, elements; - char *src, *ptr; - - if (len > view->len) { - len = view->len; - } - - if (PyBuffer_IsContiguous(view, fort)) { - /* simplest copy is all that is needed */ - memcpy(view->buf, buf, len); - return 0; - } - - /* Otherwise a more elaborate scheme is needed */ - - /* view->ndim <= 64 */ - indices = (Py_ssize_t *)PyMem_Malloc(sizeof(Py_ssize_t)*(view->ndim)); - if (indices == NULL) { - PyErr_NoMemory(); - return -1; - } - for (k=0; k<view->ndim; k++) { - indices[k] = 0; - } - - if (fort == 'F') { - addone = _Py_add_one_to_index_F; - } - else { - addone = _Py_add_one_to_index_C; - } - src = (char *)buf; // patched by CT - /* XXX : This is not going to be the fastest code in the world - several optimizations are possible. - */ - elements = len / view->itemsize; - while (elements--) { - ptr = (char *)PyBuffer_GetPointer(view, indices); // patched by CT - memcpy(ptr, src, view->itemsize); - src += view->itemsize; - addone(view->ndim, indices, view->shape); - } - - PyMem_Free(indices); - return 0; -} - -int PyObject_CopyData(PyObject *dest, PyObject *src) -{ - Pep_buffer view_dest, view_src; - int k; - Py_ssize_t *indices, elements; - char *dptr, *sptr; - - if (!PyObject_CheckBuffer(dest) || - !PyObject_CheckBuffer(src)) { - PyErr_SetString(PyExc_TypeError, - "both destination and source must be "\ - "bytes-like objects"); - return -1; - } - - if (PyObject_GetBuffer(dest, &view_dest, PyBUF_FULL) != 0) return -1; - if (PyObject_GetBuffer(src, &view_src, PyBUF_FULL_RO) != 0) { - PyBuffer_Release(&view_dest); - return -1; - } - - if (view_dest.len < view_src.len) { - PyErr_SetString(PyExc_BufferError, - "destination is too small to receive data from source"); - PyBuffer_Release(&view_dest); - PyBuffer_Release(&view_src); - return -1; - } - - if ((PyBuffer_IsContiguous(&view_dest, 'C') && - PyBuffer_IsContiguous(&view_src, 'C')) || - (PyBuffer_IsContiguous(&view_dest, 'F') && - PyBuffer_IsContiguous(&view_src, 'F'))) { - /* simplest copy is all that is needed */ - memcpy(view_dest.buf, view_src.buf, view_src.len); - PyBuffer_Release(&view_dest); - PyBuffer_Release(&view_src); - return 0; - } - - /* Otherwise a more elaborate copy scheme is needed */ - - /* XXX(nnorwitz): need to check for overflow! */ - indices = (Py_ssize_t *)PyMem_Malloc(sizeof(Py_ssize_t)*view_src.ndim); - if (indices == NULL) { - PyErr_NoMemory(); - PyBuffer_Release(&view_dest); - PyBuffer_Release(&view_src); - return -1; - } - for (k=0; k<view_src.ndim;k++) { - indices[k] = 0; - } - elements = 1; - for (k=0; k<view_src.ndim; k++) { - /* XXX(nnorwitz): can this overflow? */ - elements *= view_src.shape[k]; - } - while (elements--) { - _Py_add_one_to_index_C(view_src.ndim, indices, view_src.shape); - dptr = (char *)PyBuffer_GetPointer(&view_dest, indices); // patched by CT - sptr = (char *)PyBuffer_GetPointer(&view_src, indices); // patched by CT - memcpy(dptr, sptr, view_src.itemsize); - } - PyMem_Free(indices); - PyBuffer_Release(&view_dest); - PyBuffer_Release(&view_src); - return 0; -} - -void -PyBuffer_FillContiguousStrides(int nd, Py_ssize_t *shape, - Py_ssize_t *strides, int itemsize, - char fort) -{ - int k; - Py_ssize_t sd; - - sd = itemsize; - if (fort == 'F') { - for (k=0; k<nd; k++) { - strides[k] = sd; - sd *= shape[k]; - } - } - else { - for (k=nd-1; k>=0; k--) { - strides[k] = sd; - sd *= shape[k]; - } - } - return; -} - -int -PyBuffer_FillInfo(Pep_buffer *view, PyObject *obj, void *buf, Py_ssize_t len, - int readonly, int flags) -{ - if (view == NULL) { - PyErr_SetString(PyExc_BufferError, - "PyBuffer_FillInfo: view==NULL argument is obsolete"); - return -1; - } - - if (((flags & PyBUF_WRITABLE) == PyBUF_WRITABLE) && - (readonly == 1)) { - PyErr_SetString(PyExc_BufferError, - "Object is not writable."); - return -1; - } - - view->obj = obj; - if (obj) - Py_INCREF(obj); - view->buf = buf; - view->len = len; - view->readonly = readonly; - view->itemsize = 1; - view->format = NULL; - if ((flags & PyBUF_FORMAT) == PyBUF_FORMAT) - view->format = (char *)"B"; // patched by CT - view->ndim = 1; - view->shape = NULL; - if ((flags & PyBUF_ND) == PyBUF_ND) - view->shape = &(view->len); - view->strides = NULL; - if ((flags & PyBUF_STRIDES) == PyBUF_STRIDES) - view->strides = &(view->itemsize); - view->suboffsets = NULL; - view->internal = NULL; - return 0; -} - -void -PyBuffer_Release(Pep_buffer *view) -{ - PyObject *obj = view->obj; - PyBufferProcs *pb; - if (obj == NULL) - return; - pb = PepType_AS_BUFFER(Py_TYPE(obj)); - if (pb && pb->bf_releasebuffer) - pb->bf_releasebuffer(obj, view); - view->obj = NULL; - Py_DECREF(obj); -} - -#endif // Py_LIMITED_API diff --git a/sources/shiboken2/libshiboken/bufferprocs_py37.h b/sources/shiboken2/libshiboken/bufferprocs_py37.h deleted file mode 100644 index 6fc7a3ece..000000000 --- a/sources/shiboken2/libshiboken/bufferprocs_py37.h +++ /dev/null @@ -1,145 +0,0 @@ -/**************************************************************************** -** -** Copyright (C) 2018 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$ -** -****************************************************************************/ - -/* -PSF LICENSE AGREEMENT FOR PYTHON 3.7.0 - -1. This LICENSE AGREEMENT is between the Python Software Foundation ("PSF"), and - the Individual or Organization ("Licensee") accessing and otherwise using Python - 3.7.0 software in source or binary form and its associated documentation. - -2. Subject to the terms and conditions of this License Agreement, PSF hereby - grants Licensee a nonexclusive, royalty-free, world-wide license to reproduce, - analyze, test, perform and/or display publicly, prepare derivative works, - distribute, and otherwise use Python 3.7.0 alone or in any derivative - version, provided, however, that PSF's License Agreement and PSF's notice of - copyright, i.e., "Copyright © 2001-2018 Python Software Foundation; All Rights - Reserved" are retained in Python 3.7.0 alone or in any derivative version - prepared by Licensee. - -3. In the event Licensee prepares a derivative work that is based on or - incorporates Python 3.7.0 or any part thereof, and wants to make the - derivative work available to others as provided herein, then Licensee hereby - agrees to include in any such work a brief summary of the changes made to Python - 3.7.0. - -4. PSF is making Python 3.7.0 available to Licensee on an "AS IS" basis. - PSF MAKES NO REPRESENTATIONS OR WARRANTIES, EXPRESS OR IMPLIED. BY WAY OF - EXAMPLE, BUT NOT LIMITATION, PSF MAKES NO AND DISCLAIMS ANY REPRESENTATION OR - WARRANTY OF MERCHANTABILITY OR FITNESS FOR ANY PARTICULAR PURPOSE OR THAT THE - USE OF PYTHON 3.7.0 WILL NOT INFRINGE ANY THIRD PARTY RIGHTS. - -5. PSF SHALL NOT BE LIABLE TO LICENSEE OR ANY OTHER USERS OF PYTHON 3.7.0 - FOR ANY INCIDENTAL, SPECIAL, OR CONSEQUENTIAL DAMAGES OR LOSS AS A RESULT OF - MODIFYING, DISTRIBUTING, OR OTHERWISE USING PYTHON 3.7.0, OR ANY DERIVATIVE - THEREOF, EVEN IF ADVISED OF THE POSSIBILITY THEREOF. - -6. This License Agreement will automatically terminate upon a material breach of - its terms and conditions. - -7. Nothing in this License Agreement shall be deemed to create any relationship - of agency, partnership, or joint venture between PSF and Licensee. This License - Agreement does not grant permission to use PSF trademarks or trade name in a - trademark sense to endorse or promote products or services of Licensee, or any - third party. - -8. By copying, installing or otherwise using Python 3.7.0, Licensee agrees - to be bound by the terms and conditions of this License Agreement. -*/ - -#ifndef BUFFER_REENABLE_H -#define BUFFER_REENABLE_H - -/* buffer interface */ -// This has been renamed to Pep_buffer and will be used. -typedef struct bufferinfo { - void *buf; - PyObject *obj; /* owned reference */ - Py_ssize_t len; - Py_ssize_t itemsize; /* This is Py_ssize_t so it can be - pointed to by strides in simple case.*/ - int readonly; - int ndim; - char *format; - Py_ssize_t *shape; - Py_ssize_t *strides; - Py_ssize_t *suboffsets; - void *internal; -} Pep_buffer; - -typedef int (*getbufferproc)(PyObject *, Pep_buffer *, int); -typedef void (*releasebufferproc)(PyObject *, Pep_buffer *); - -/* Maximum number of dimensions */ -#define PyBUF_MAX_NDIM 64 - -/* Flags for getting buffers */ -#define PyBUF_SIMPLE 0 -#define PyBUF_WRITABLE 0x0001 -/* we used to include an E, backwards compatible alias */ -#define PyBUF_WRITEABLE PyBUF_WRITABLE -#define PyBUF_FORMAT 0x0004 -#define PyBUF_ND 0x0008 -#define PyBUF_STRIDES (0x0010 | PyBUF_ND) -#define PyBUF_C_CONTIGUOUS (0x0020 | PyBUF_STRIDES) -#define PyBUF_F_CONTIGUOUS (0x0040 | PyBUF_STRIDES) -#define PyBUF_ANY_CONTIGUOUS (0x0080 | PyBUF_STRIDES) -#define PyBUF_INDIRECT (0x0100 | PyBUF_STRIDES) - -#define PyBUF_CONTIG (PyBUF_ND | PyBUF_WRITABLE) -#define PyBUF_CONTIG_RO (PyBUF_ND) - -#define PyBUF_STRIDED (PyBUF_STRIDES | PyBUF_WRITABLE) -#define PyBUF_STRIDED_RO (PyBUF_STRIDES) - -#define PyBUF_RECORDS (PyBUF_STRIDES | PyBUF_WRITABLE | PyBUF_FORMAT) -#define PyBUF_RECORDS_RO (PyBUF_STRIDES | PyBUF_FORMAT) - -#define PyBUF_FULL (PyBUF_INDIRECT | PyBUF_WRITABLE | PyBUF_FORMAT) -#define PyBUF_FULL_RO (PyBUF_INDIRECT | PyBUF_FORMAT) - - -#define PyBUF_READ 0x100 -#define PyBUF_WRITE 0x200 - -/* End buffer interface */ -LIBSHIBOKEN_API PyObject *PyMemoryView_FromBuffer(Pep_buffer *info); -#define Py_buffer Pep_buffer - -#endif // BUFFER_REENABLE_H diff --git a/sources/shiboken2/libshiboken/debugfreehook.cpp b/sources/shiboken2/libshiboken/debugfreehook.cpp deleted file mode 100644 index 3d52d88dc..000000000 --- a/sources/shiboken2/libshiboken/debugfreehook.cpp +++ /dev/null @@ -1,194 +0,0 @@ -/**************************************************************************** -** -** Copyright (C) 2016 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$ -** -****************************************************************************/ - -#include "debugfreehook.h" -#include "bindingmanager.h" -#include "gilstate.h" - -#if defined(_WIN32) && defined(_DEBUG) -#include <crtdbg.h> -#include <windows.h> -#endif - -#ifdef __GLIBC__ -#include <malloc.h> -#endif - -#ifdef __APPLE__ -#include <malloc/malloc.h> -#include <mach/mach.h> -#include <mach/mach_vm.h> -#endif - -#ifdef SHIBOKEN_INSTALL_FREE_DEBUG_HOOK -extern "C" { - -static int testPointerBeingFreed(void *ptr) -{ - // It is an error for a deleted pointer address to still be registered - // in the BindingManager - if (Shiboken::BindingManager::instance().hasWrapper(ptr)) { - Shiboken::GilState state; - - SbkObject *wrapper = Shiboken::BindingManager::instance().retrieveWrapper(ptr); - - fprintf(stderr, "SbkObject still in binding map when deleted: "); - PyObject_Print(reinterpret_cast<PyObject *>(wrapper), stderr, 0); - fprintf(stderr, "\n"); - -#ifdef _WIN32 - DebugBreak(); -#else - assert(0); -#endif - return FALSE; - } - - return TRUE; -} - -#if defined(_WIN32) && defined(_DEBUG) -static _CRT_ALLOC_HOOK lastCrtAllocHook; -static int DebugAllocHook(int nAllocType, void *pvData, - size_t nSize, int nBlockUse, long lRequest, - const unsigned char * szFileName, int nLine) -{ - // It is an error for a deleted pointer address to still be registered - // in the BindingManager - if ( nAllocType == _HOOK_FREE) { - if ( !testPointerBeingFreed(pvData) ) { - return 0; - } - } - - if ( lastCrtAllocHook != NULL ) { - return lastCrtAllocHook(nAllocType, pvData, nSize, nBlockUse, lRequest, - szFileName, nLine); - } - - return 1; -} -#endif // _WIN32 && _DEBUG - -#ifdef __GLIBC__ -static void (*lastFreeHook)(void *ptr, const void *caller); -static void DebugFreeHook(void *ptr, const void *caller) -{ - testPointerBeingFreed(ptr); - - if ( lastFreeHook != NULL ) - lastFreeHook(ptr, caller); -} -#endif // __GLIBC__ - -#ifdef __APPLE__ -static malloc_zone_t lastMallocZone; -static void DebugFreeHook(malloc_zone_t *zone, void *ptr) -{ - testPointerBeingFreed(ptr); - - if ( lastMallocZone.free != NULL ) - lastMallocZone.free(zone, ptr); -} -static void DebugFreeDefiniteSizeHook(malloc_zone_t *zone, void *ptr, size_t size) -{ - testPointerBeingFreed(ptr); - - if ( lastMallocZone.free_definite_size != NULL ) - lastMallocZone.free_definite_size(zone, ptr, size); -} -#endif __APPLE__ - -void debugInstallFreeHook(void) -{ -#if defined(_WIN32) && defined(_DEBUG) - lastCrtAllocHook = _CrtSetAllocHook(DebugAllocHook); -#endif - -#ifdef __GLIBC__ - // __free_hook is not thread safe so it marked as deprecated. Use here - // is hopefully safe and should catch errors in a single threaded program - // and only miss some in a multithreaded program - lastFreeHook = __free_hook; - __free_hook = DebugFreeHook; -#endif - -#ifdef __APPLE__ - malloc_zone_t *zone = malloc_default_zone(); - assert(zone != NULL); - //remove the write protection from the zone struct - if (zone->version >= 8) { - vm_protect(mach_task_self(), (uintptr_t)zone, sizeof(*zone), 0, VM_PROT_READ | VM_PROT_WRITE); - } - lastMallocZone = *zone; - zone->free = DebugFreeHook; - zone->free_definite_size = DebugFreeDefiniteSizeHook; - if (zone->version >= 8) { - vm_protect(mach_task_self(), (uintptr_t)zone, sizeof(*zone), 0, VM_PROT_READ); - } -#endif -} - -void debugRemoveFreeHook(void) -{ -#if defined(_WIN32) && defined(_DEBUG) - _CrtSetAllocHook(lastCrtAllocHook); -#endif - -#ifdef __GLIBC__ - __free_hook = lastFreeHook; -#endif - -#ifdef __APPLE__ - malloc_zone_t *zone = malloc_default_zone(); - assert(zone != NULL); - //remove the write protection from the zone struct - if (zone->version >= 8) { - vm_protect(mach_task_self(), (uintptr_t)zone, sizeof(*zone), 0, VM_PROT_READ | VM_PROT_WRITE); - } - zone->free = lastMallocZone.free; - zone->free_definite_size = lastMallocZone.free_definite_size; - if (zone->version >= 8) { - vm_protect(mach_task_self(), (uintptr_t)zone, sizeof(*zone), 0, VM_PROT_READ); - } -#endif -} - -} // extern "C" -#endif // SHIBOKEN_INSTALL_DEBUG_FREE_HOOK diff --git a/sources/shiboken2/libshiboken/debugfreehook.h b/sources/shiboken2/libshiboken/debugfreehook.h deleted file mode 100644 index fdf98d5d3..000000000 --- a/sources/shiboken2/libshiboken/debugfreehook.h +++ /dev/null @@ -1,61 +0,0 @@ -/**************************************************************************** -** -** Copyright (C) 2016 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$ -** -****************************************************************************/ - -#ifndef DEBUGFREEHOOK_H -#define DEBUGFREEHOOK_H - -// These functions enable C library runtime hooks to try to catch cases where -// C++ object addresses remain in hash table of valid wrappers when the address -// is passed to free. The hooks are probably not thread safe and thus -// should only be enabled in single threaded environments - -// To enable the hook, uncomment the following define. -//#define SHIBOKEN_INSTALL_FREE_DEBUG_HOOK - -#ifdef SHIBOKEN_INSTALL_FREE_DEBUG_HOOK -extern "C" { - -void debugInstallFreeHook(void); -void debugRemoveFreeHook(void); - -} // extern "C" - -#endif // SHIBOKEN_INSTALL_FREE_DEBUG_HOOK - -#endif // DEBUGFREEHOOK_H diff --git a/sources/shiboken2/libshiboken/embed/embedding_generator.py b/sources/shiboken2/libshiboken/embed/embedding_generator.py deleted file mode 100644 index 8fb498008..000000000 --- a/sources/shiboken2/libshiboken/embed/embedding_generator.py +++ /dev/null @@ -1,239 +0,0 @@ -############################################################################# -## -## Copyright (C) 2019 The Qt Company Ltd. -## Contact: https://www.qt.io/licensing/ -## -## This file is part of PySide2. -## -## $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$ -## -############################################################################# - -""" -embedding_generator.py - -This file takes the content of the two supported directories and inserts -it into a zip file. The zip file is then converted into a C++ source -file that can easily be unpacked again with Python (see signature.cpp, -constant 'PySide_PythonCode'). - -Note that this _is_ a zipfile, but since it is embedded into the shiboken -binary, we cannot use the zipimport module from Python. -But a similar solution is possible that allows for normal imports. - -See signature_bootstrap.py for details. -""" - -from __future__ import print_function, absolute_import - -import sys -import os -import subprocess -import textwrap -import tempfile -import argparse -import marshal -import traceback - -# work_dir is set to the source for testing, onl. -# It can be overridden in the command line. -work_dir = os.path.abspath(os.path.dirname(__file__)) -embed_dir = work_dir -cur_dir = os.getcwd() -source_dir = os.path.normpath(os.path.join(work_dir, "..", "..", "..")) -assert os.path.basename(source_dir) == "sources" -build_script_dir = os.path.normpath(os.path.join(work_dir, "..", "..", "..", "..")) -assert os.path.exists(os.path.join(build_script_dir, "build_scripts")) - -sys.path.insert(0, build_script_dir) - -from build_scripts import utils - - -def runpy(cmd, **kw): - subprocess.call([sys.executable, '-E'] + cmd.split(), **kw) - - -def create_zipfile(limited_api): - """ - Collect all Python files, compile them, create a zip file - and make a chunked base64 encoded file from it. - """ - zip_name = "signature.zip" - inc_name = "signature_inc.h" - flag = '-b' - os.chdir(work_dir) - - # Remove all left-over py[co] and other files first, in case we use '--reuse-build'. - # Note that we could improve that with the PyZipfile function to use .pyc files - # in different folders, but that makes only sense when COIN allows us to have - # multiple Python versions in parallel. - from os.path import join, getsize - for root, dirs, files in os.walk(work_dir): - for name in files: - fpath = os.path.join(root, name) - ew = name.endswith - if ew(".pyc") or ew(".pyo") or ew(".zip") or ew(".inc"): - os.remove(fpath) - # We copy every Python file into this dir, but only for the right version. - # For testing in the source dir, we need to filter. - ignore = [] - utils.copydir(os.path.join(source_dir, "shiboken2", "shibokenmodule", "files.dir", "shibokensupport"), - os.path.join(work_dir, "shibokensupport"), - ignore=ignore, file_filter_function=lambda name, n2: name.endswith(".py")) - if embed_dir != work_dir: - utils.copyfile(os.path.join(embed_dir, "signature_bootstrap.py"), work_dir) - - if limited_api: - pass # We cannot compile, unless we have folders per Python version - else: - files = ' '.join(fn for fn in os.listdir('.')) - runpy('-m compileall -q {flag} {files}'.format(**locals())) - files = ' '.join(fn for fn in os.listdir('.') if not fn == zip_name) - runpy('-m zipfile -c {zip_name} {files}'.format(**locals())) - tmp = tempfile.TemporaryFile(mode="w+") - runpy('-m base64 {zip_name}'.format(**locals()), stdout=tmp) - # now generate the include file - tmp.seek(0) - with open(inc_name, "w") as inc: - _embed_file(tmp, inc) - tmp.close() - # also generate a simple embeddable .pyc file for signature_bootstrap.pyc - boot_name = "signature_bootstrap.py" if limited_api else "signature_bootstrap.pyc" - with open(boot_name, "rb") as ldr, open("signature_bootstrap_inc.h", "w") as inc: - _embed_bytefile(ldr, inc, limited_api) - os.chdir(cur_dir) - - -def _embed_file(fin, fout): - """ - Format a text file for embedding in a C++ source file. - """ - # MSVC has a 64k string limitation. In C, it would be easy to create an - # array of 64 byte strings and use them as one big array. In C++ this does - # not work, since C++ insists in having the terminating nullbyte. - # Therefore, we split the string after an arbitrary number of lines - # (chunked file). - limit = 50 - text = fin.readlines() - print(textwrap.dedent(""" - /* - * This is a ZIP archive of all Python files in the directory - * "shiboken2/shibokenmodule/files.dir/shibokensupport/signature" - * There is also a toplevel file "signature_bootstrap.py[c]" that will be - * directly executed from C++ as a bootstrap loader. - */ - """).strip(), file=fout) - block, blocks = 0, len(text) // limit + 1 - for idx, line in enumerate(text): - if idx % limit == 0: - comma = "," if block else "" - block += 1 - print(file=fout) - print('/* Block {block} of {blocks} */{comma}'.format(**locals()), file=fout) - print('\"{}\"'.format(line.strip()), file=fout) - print('/* Sentinel */, \"\"', file=fout) - - -def _embed_bytefile(fin, fout, is_text): - """ - Format a binary file for embedding in a C++ source file. - This version works directly with a single .pyc file. - """ - fname = fin.name - remark = ("No .pyc file because '--LIMITED-API=yes'" if is_text else - "The .pyc header is stripped away") - print(textwrap.dedent(""" - /* - * This is the file "{fname}" as a simple byte array. - * It can be directly embedded without any further processing. - * {remark}. - */ - """).format(**locals()).strip(), file=fout) - headsize = ( 0 if is_text else - 16 if sys.version_info >= (3, 7) else 12 if sys.version_info >= (3, 3) else 8) - binstr = fin.read()[headsize:] - if is_text: - try: - compile(binstr, fin.name, "exec") - except SyntaxError as e: - print(e) - traceback.print_exc(file=sys.stdout) - print(textwrap.dedent(""" - ************************************************************************* - *** - *** Could not compile the boot loader '{fname}'! - *** - ************************************************************************* - """).format(version=sys.version_info[:3], **locals())) - raise SystemError - else: - try: - marshal.loads(binstr) - except ValueError as e: - print(e) - traceback.print_exc(file=sys.stdout) - print(textwrap.dedent(""" - ************************************************************************* - *** - *** This Python version {version} seems to have a new .pyc header size. - *** Please correct the 'headsize' constant ({headsize}). - *** - ************************************************************************* - """).format(version=sys.version_info[:3], **locals())) - raise SystemError - - print(file=fout) - use_ord = sys.version_info[0] == 2 - for i in range(0, len(binstr), 16): - for c in bytes(binstr[i : i + 16]): - print("{:#4},".format(ord(c) if use_ord else c), file=fout, end="") - print(file=fout) - print("/* End Of File */", file=fout) - - -def str2bool(v): - if v.lower() in ('yes', 'true', 't', 'y', '1'): - return True - elif v.lower() in ('no', 'false', 'f', 'n', '0'): - return False - else: - raise argparse.ArgumentTypeError('Boolean value expected.') - - -if __name__ == "__main__": - parser = argparse.ArgumentParser() - parser.add_argument('--cmake-dir', nargs="?") - parser.add_argument('--limited-api', type=str2bool) - args = parser.parse_args() - if args.cmake_dir: - work_dir = os.path.abspath(args.cmake_dir) - create_zipfile(args.limited_api) diff --git a/sources/shiboken2/libshiboken/embed/module_collector.py b/sources/shiboken2/libshiboken/embed/module_collector.py deleted file mode 100644 index 3eaa0be5d..000000000 --- a/sources/shiboken2/libshiboken/embed/module_collector.py +++ /dev/null @@ -1,105 +0,0 @@ -# This Python file uses the following encoding: utf-8 -# It has been edited by fix-complaints.py . - -############################################################################# -## -## 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$ -## -############################################################################# - -""" -module_collector.py - -Collect a number of modules listed on the command line. - -The purpose of this script is to generate the scripts needed for -a complete isolation of the signature extension. - -Usage: - -Run this script in one of the used python versions. -It will create an executable archive of the files on the command line. -""" - -import sys -import os -import argparse -import pickle -from textwrap import dedent - -def source_archive(module, modname): - fname = os.path.splitext(module.__file__)[0] + ".py" - with open(fname) as source: - text = source.read() - encoded = text.replace("'''", "(triple_single)") - # modname = module.__name__ - # Do not use: Some modules rename themselves! - version = ".".join(map(str, sys.version_info[:3])) - shortname = os.path.basename(fname) - preamble = dedent(r""" - # BEGIN SOURCE ARCHIVE Python {version} module {modname} - - sources = {{}} if "sources" not in globals() else sources - sources["{modname}"] = '''\ - {encoded}'''.replace("(triple_single)", "'''") - - # END SOURCE ARCHIVE Python {version} module {modname} - """).format(**locals()) - return preamble - -def read_all(modules): - collected = "" - for modname in modules: - mod = __import__(modname) - collected += source_archive(mod, modname) - return collected - -def license_header(): - license = os.path.join(os.path.dirname(__file__), "qt_python_license.txt") - with open(license) as f: - return f.read() - -if __name__ == "__main__": - parser = argparse.ArgumentParser() - parser.add_argument('modules', nargs="+") - args = parser.parse_args() - print("modules:", args.modules) - ret = license_header() + read_all(args.modules) - ma_mi = "_".join(map(str, sys.version_info[:2])) - outpath = os.path.join(os.path.dirname(__file__), "..", "..", "shibokenmodule", - "files.dir", "shibokensupport", "python_minilib_{ma_mi}.py".format(**locals())) - with open(outpath, "w") as f: - f.write(ret) diff --git a/sources/shiboken2/libshiboken/embed/qt_python_license.txt b/sources/shiboken2/libshiboken/embed/qt_python_license.txt deleted file mode 100644 index b5f8c581a..000000000 --- a/sources/shiboken2/libshiboken/embed/qt_python_license.txt +++ /dev/null @@ -1,87 +0,0 @@ -# This Python file uses the following encoding: utf-8 -# It has been edited by fix-complaints.py . - -############################################################################# -## -## 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$ -## -############################################################################# - -## -## PSF LICENSE AGREEMENT FOR PYTHON 3.7.0 -## -## 1. This LICENSE AGREEMENT is between the Python Software Foundation ("PSF"), and -## the Individual or Organization ("Licensee") accessing and otherwise using Python -## 3.7.0 software in source or binary form and its associated documentation. -## -## 2. Subject to the terms and conditions of this License Agreement, PSF hereby -## grants Licensee a nonexclusive, royalty-free, world-wide license to reproduce, -## analyze, test, perform and/or display publicly, prepare derivative works, -## distribute, and otherwise use Python 3.7.0 alone or in any derivative -## version, provided, however, that PSF's License Agreement and PSF's notice of -## copyright, i.e., "Copyright © 2001-2018 Python Software Foundation; All Rights -## Reserved" are retained in Python 3.7.0 alone or in any derivative version -## prepared by Licensee. -## -## 3. In the event Licensee prepares a derivative work that is based on or -## incorporates Python 3.7.0 or any part thereof, and wants to make the -## derivative work available to others as provided herein, then Licensee hereby -## agrees to include in any such work a brief summary of the changes made to Python -## 3.7.0. -## -## 4. PSF is making Python 3.7.0 available to Licensee on an "AS IS" basis. -## PSF MAKES NO REPRESENTATIONS OR WARRANTIES, EXPRESS OR IMPLIED. BY WAY OF -## EXAMPLE, BUT NOT LIMITATION, PSF MAKES NO AND DISCLAIMS ANY REPRESENTATION OR -## WARRANTY OF MERCHANTABILITY OR FITNESS FOR ANY PARTICULAR PURPOSE OR THAT THE -## USE OF PYTHON 3.7.0 WILL NOT INFRINGE ANY THIRD PARTY RIGHTS. -## -## 5. PSF SHALL NOT BE LIABLE TO LICENSEE OR ANY OTHER USERS OF PYTHON 3.7.0 -## FOR ANY INCIDENTAL, SPECIAL, OR CONSEQUENTIAL DAMAGES OR LOSS AS A RESULT OF -## MODIFYING, DISTRIBUTING, OR OTHERWISE USING PYTHON 3.7.0, OR ANY DERIVATIVE -## THEREOF, EVEN IF ADVISED OF THE POSSIBILITY THEREOF. -## -## 6. This License Agreement will automatically terminate upon a material breach of -## its terms and conditions. -## -## 7. Nothing in this License Agreement shall be deemed to create any relationship -## of agency, partnership, or joint venture between PSF and Licensee. This License -## Agreement does not grant permission to use PSF trademarks or trade name in a -## trademark sense to endorse or promote products or services of Licensee, or any -## third party. -## -## 8. By copying, installing or otherwise using Python 3.7.0, Licensee agrees -## to be bound by the terms and conditions of this License Agreement. -## diff --git a/sources/shiboken2/libshiboken/embed/signature_bootstrap.py b/sources/shiboken2/libshiboken/embed/signature_bootstrap.py deleted file mode 100644 index b7d9d2793..000000000 --- a/sources/shiboken2/libshiboken/embed/signature_bootstrap.py +++ /dev/null @@ -1,180 +0,0 @@ -############################################################################# -## -## Copyright (C) 2019 The Qt Company Ltd. -## Contact: https://www.qt.io/licensing/ -## -## This file is part of PySide2. -## -## $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$ -## -############################################################################# - -""" -signature_bootstrap.py ----------------------- - -This file was originally directly embedded into the C source. -After it grew more and more, I now prefer to have it as Python file. - -Meanwhile, there is also no more a stub loader necessary: -Because we meanwhile have embedding support, we could also load this file -directly from a .pyc file. - -This file replaces the hard to read Python stub in 'signature.cpp', and we -could distinguish better between bootstrap related functions and loader -functions. -It is embedded into 'signature.cpp' as "embed/signature_bootstrap.inc". -""" - -from __future__ import print_function, absolute_import - -recursion_trap = 0 - -# We avoid real imports in phase 1 that could fail (simply removed all). -# Python 2 is not able to import when the extension import is still active. -# Phase 1 simply defines the functions, which will be used in Phase 2. - -def bootstrap(): - import sys - import os - import tempfile - import traceback - from contextlib import contextmanager - - global recursion_trap - if recursion_trap: - # we are probably called from outside, already - print("Recursion occurred in Bootstrap. Did you start by hand? Then it's ok.") - print("But you should trigger start by '_init_pyside_extension()', only!") - recursion_trap += 1 - - @contextmanager - def ensure_shibokensupport(support_path): - # Make sure that we always have the shibokensupport containing package first. - # Also remove any prior loaded module of this name, just in case. - sys.path.insert(0, support_path) - - sbks = "shibokensupport" - if sbks in sys.modules: - del sys.modules[sbks] - prefix = sbks + "." - for key in list(key for key in sys.modules if key.startswith(prefix)): - del sys.modules[key] - try: - import shibokensupport - yield - except Exception as e: - print("Problem importing shibokensupport:") - print(e) - traceback.print_exc() - print("sys.path:") - for p in sys.path: - print(" " + p) - sys.stdout.flush() - sys.exit(-1) - sys.path.remove(support_path) - - try: - import shiboken2 as root - except ImportError: - # uninstalled case without ctest, try only this one which has __init__: - import shibokenmodule as root - rp = os.path.realpath(os.path.dirname(root.__file__)) - # This can be the shiboken2 directory or the binary module, so search. - look_for = os.path.join("files.dir", "shibokensupport", "signature", "loader.py") - while len(rp) > 3 and not os.path.exists(os.path.join(rp, look_for)): - rp = os.path.abspath(os.path.join(rp, "..")) - - # Here we decide if we work embedded or not. - embedding_var = "pyside_uses_embedding" - use_embedding = bool(getattr(sys, embedding_var, False)) - # We keep the zip file for inspection if the sys variable has been set. - keep_zipfile = hasattr(sys, embedding_var) - loader_path = os.path.join(rp, look_for) - files_dir = os.path.abspath(os.path.join(loader_path, "..", "..", "..")) - assert files_dir.endswith("files.dir") - - # We report in sys what we used. We could put more here as well. - if not os.path.exists(loader_path): - use_embedding = True - support_path = prepare_zipfile() if use_embedding else files_dir - setattr(sys, embedding_var, use_embedding) - - try: - with ensure_shibokensupport(support_path): - from shibokensupport.signature import loader - - except Exception as e: - print('Exception:', e) - traceback.print_exc(file=sys.stdout) - - finally: - if use_embedding and not keep_zipfile: - # clear the temp zipfile - try: - os.remove(support_path) - except OSError as e: - print(e) - print("Error deleting {support_path}, ignored".format(**locals())) - return loader - -# New functionality: Loading from a zip archive. -# There exists the zip importer, but as it is written, only real zip files are -# supported. Before I will start an own implementation, it is easiest to use -# a temporary zip file. - -def prepare_zipfile(): - """ - Write the zip file to a real file and return its name. - It will be implicitly opened as such when we add the name to sys.path . - """ - import base64 - import tempfile - import os - import zipfile - - # 'zipstring_sequence' comes from signature.cpp - zipbytes = base64.b64decode(''.join(zipstring_sequence)) - fd, fname = tempfile.mkstemp(prefix='embedded.', suffix='.zip') - os.write(fd, zipbytes) - os.close(fd) - # Let us test the zipfile if it really is one. - # Otherwise, zipimporter would simply ignore it without notice. - try: - z = zipfile.ZipFile(fname) - z.close() - except zipfile.BadZipFile as e: - print('Broken Zip File:', e) - traceback.print_exc(file=sys.stdout) - finally: - return fname - -# eof diff --git a/sources/shiboken2/libshiboken/gilstate.cpp b/sources/shiboken2/libshiboken/gilstate.cpp deleted file mode 100644 index 76a4d0e61..000000000 --- a/sources/shiboken2/libshiboken/gilstate.cpp +++ /dev/null @@ -1,74 +0,0 @@ -/**************************************************************************** -** -** Copyright (C) 2016 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$ -** -****************************************************************************/ - -#include "gilstate.h" - -namespace Shiboken -{ - -GilState::GilState() -{ - if (Py_IsInitialized()) { - m_gstate = PyGILState_Ensure(); - m_locked = true; - } -} - -GilState::~GilState() -{ - release(); -} - -void GilState::release() -{ - if (m_locked && Py_IsInitialized()) { - PyGILState_Release(m_gstate); - m_locked = false; - } -} - -// Abandon the lock: Only for special situations, like termination of a -// POSIX thread (PYSIDE 1282). -void GilState::abandon() -{ - m_locked = false; -} - -} // namespace Shiboken - diff --git a/sources/shiboken2/libshiboken/gilstate.h b/sources/shiboken2/libshiboken/gilstate.h deleted file mode 100644 index fbf39ead0..000000000 --- a/sources/shiboken2/libshiboken/gilstate.h +++ /dev/null @@ -1,69 +0,0 @@ -/**************************************************************************** -** -** Copyright (C) 2016 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$ -** -****************************************************************************/ - -#ifndef GILSTATE_H -#define GILSTATE_H - -#include <shibokenmacros.h> -#include "sbkpython.h" - -namespace Shiboken -{ - -class LIBSHIBOKEN_API GilState -{ -public: - GilState(const GilState &) = delete; - GilState(GilState &&) = delete; - GilState &operator=(const GilState &) = delete; - GilState &operator=(GilState &&) = delete; - - GilState(); - ~GilState(); - void release(); - void abandon(); -private: - PyGILState_STATE m_gstate; - bool m_locked = false; -}; - -} // namespace Shiboken - -#endif // GILSTATE_H - diff --git a/sources/shiboken2/libshiboken/helper.cpp b/sources/shiboken2/libshiboken/helper.cpp deleted file mode 100644 index cad48951e..000000000 --- a/sources/shiboken2/libshiboken/helper.cpp +++ /dev/null @@ -1,276 +0,0 @@ -/**************************************************************************** -** -** Copyright (C) 2020 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$ -** -****************************************************************************/ - -#include "helper.h" -#include "sbkstring.h" -#include "sbkstaticstrings.h" - -#include <iomanip> -#include <iostream> - -#include <stdarg.h> - -#ifdef _WIN32 -# ifndef NOMINMAX -# define NOMINMAX -# endif -# include <windows.h> -#else -# include <pthread.h> -#endif - -#include <algorithm> - -static void formatPyTypeObject(const PyTypeObject *obj, std::ostream &str) -{ - if (obj) { - str << '"' << obj->tp_name << "\", 0x" << std::hex - << obj->tp_flags << std::dec; - if (obj->tp_flags & Py_TPFLAGS_HEAPTYPE) - str << " [heaptype]"; - if (obj->tp_flags & Py_TPFLAGS_BASETYPE) - str << " [base]"; - if (obj->tp_flags & Py_TPFLAGS_HAVE_GC) - str << " [gc]"; - if (obj->tp_flags & Py_TPFLAGS_LONG_SUBCLASS) - str << " [long]"; - if (obj->tp_flags & Py_TPFLAGS_LIST_SUBCLASS) - str << " [list]"; - if (obj->tp_flags & Py_TPFLAGS_TUPLE_SUBCLASS) - str << " [tuple]"; - if (obj->tp_flags & Py_TPFLAGS_BYTES_SUBCLASS) - str << " [bytes]"; - if (obj->tp_flags & Py_TPFLAGS_UNICODE_SUBCLASS) - str << " [unicode]"; - if (obj->tp_flags & Py_TPFLAGS_DICT_SUBCLASS) - str << " [dict]"; - if (obj->tp_flags & Py_TPFLAGS_TYPE_SUBCLASS) - str << " [type]"; - if (obj->tp_flags & Py_TPFLAGS_IS_ABSTRACT) - str << " [abstract]"; - } else { - str << '0'; - } -} - -static void formatPyObject(PyObject *obj, std::ostream &str); - -static void formatPySequence(PyObject *obj, std::ostream &str) -{ - const Py_ssize_t size = PySequence_Size(obj); - const Py_ssize_t printSize = std::min(size, Py_ssize_t(5)); - str << size << " <"; - for (Py_ssize_t i = 0; i < printSize; ++i) { - if (i) - str << ", "; - str << '('; - PyObject *item = PySequence_GetItem(obj, i); - formatPyObject(item, str); - str << ')'; - Py_XDECREF(item); - } - if (printSize < size) - str << ",..."; - str << '>'; -} - -static void formatPyObject(PyObject *obj, std::ostream &str) -{ - if (obj) { - formatPyTypeObject(obj->ob_type, str); - str << ", "; - if (PyLong_Check(obj)) - str << PyLong_AsLong(obj); - else if (PyFloat_Check(obj)) - str << PyFloat_AsDouble(obj); - else if (PyUnicode_Check(obj)) - str << '"' << _PepUnicode_AsString(obj) << '"'; - else if (PySequence_Check(obj)) - formatPySequence(obj, str); - else - str << "<unknown>"; - } else { - str << '0'; - } -} - -namespace Shiboken -{ - -debugPyObject::debugPyObject(PyObject *o) : m_object(o) -{ -} - -debugPyTypeObject::debugPyTypeObject(const PyTypeObject *o) : m_object(o) -{ -} - -std::ostream &operator<<(std::ostream &str, const debugPyTypeObject &o) -{ - str << "PyTypeObject("; - formatPyTypeObject(o.m_object, str); - str << ')'; - return str; -} - -std::ostream &operator<<(std::ostream &str, const debugPyObject &o) -{ - str << "PyObject("; - formatPyObject(o.m_object, str); - str << ')'; - return str; -} - -// PySide-510: Changed from PySequence to PyList, which is correct. -bool listToArgcArgv(PyObject *argList, int *argc, char ***argv, const char *defaultAppName) -{ - if (!PyList_Check(argList)) - return false; - - if (!defaultAppName) - defaultAppName = "PySideApplication"; - - // Check all items - Shiboken::AutoDecRef args(PySequence_Fast(argList, nullptr)); - int numArgs = int(PySequence_Fast_GET_SIZE(argList)); - for (int i = 0; i < numArgs; ++i) { - PyObject *item = PyList_GET_ITEM(args.object(), i); - if (!PyBytes_Check(item) && !PyUnicode_Check(item)) - return false; - } - - bool hasEmptyArgList = numArgs == 0; - if (hasEmptyArgList) - numArgs = 1; - - *argc = numArgs; - *argv = new char *[*argc]; - - if (hasEmptyArgList) { - // Try to get the script name - PyObject *globals = PyEval_GetGlobals(); - PyObject *appName = PyDict_GetItem(globals, Shiboken::PyMagicName::file()); - (*argv)[0] = strdup(appName ? Shiboken::String::toCString(appName) : defaultAppName); - } else { - for (int i = 0; i < numArgs; ++i) { - PyObject *item = PyList_GET_ITEM(args.object(), i); - char *string = nullptr; - if (Shiboken::String::check(item)) { - string = strdup(Shiboken::String::toCString(item)); - } - (*argv)[i] = string; - } - } - - return true; -} - -int *sequenceToIntArray(PyObject *obj, bool zeroTerminated) -{ - AutoDecRef seq(PySequence_Fast(obj, "Sequence of ints expected")); - if (seq.isNull()) - return nullptr; - - Py_ssize_t size = PySequence_Fast_GET_SIZE(seq.object()); - int *array = new int[size + (zeroTerminated ? 1 : 0)]; - - for (int i = 0; i < size; i++) { - PyObject *item = PySequence_Fast_GET_ITEM(seq.object(), i); - if (!PyInt_Check(item)) { - PyErr_SetString(PyExc_TypeError, "Sequence of ints expected"); - delete[] array; - return nullptr; - } - array[i] = PyInt_AsLong(item); - } - - if (zeroTerminated) - array[size] = 0; - - return array; -} - - -int warning(PyObject *category, int stacklevel, const char *format, ...) -{ - va_list args; - va_start(args, format); -#ifdef _WIN32 - va_list args2 = args; -#else - va_list args2; - va_copy(args2, args); -#endif - - // check the necessary memory - int size = vsnprintf(nullptr, 0, format, args) + 1; - auto message = new char[size]; - int result = 0; - if (message) { - // format the message - vsnprintf(message, size, format, args2); - result = PyErr_WarnEx(category, message, stacklevel); - delete [] message; - } - va_end(args2); - va_end(args); - return result; -} - -ThreadId currentThreadId() -{ -#if defined(_WIN32) - return GetCurrentThreadId(); -#elif defined(__APPLE_CC__) - return reinterpret_cast<ThreadId>(pthread_self()); -#else - return pthread_self(); -#endif -} - -// Internal, used by init() from main thread -static ThreadId _mainThreadId{0}; -void _initMainThreadId() { _mainThreadId = currentThreadId(); } - -ThreadId mainThreadId() -{ - return _mainThreadId; -} - -} // namespace Shiboken diff --git a/sources/shiboken2/libshiboken/helper.h b/sources/shiboken2/libshiboken/helper.h deleted file mode 100644 index 7e46f3d93..000000000 --- a/sources/shiboken2/libshiboken/helper.h +++ /dev/null @@ -1,124 +0,0 @@ -/**************************************************************************** -** -** Copyright (C) 2016 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$ -** -****************************************************************************/ - -#ifndef HELPER_H -#define HELPER_H - -#include "sbkpython.h" -#include "shibokenmacros.h" -#include "autodecref.h" - -#include <iosfwd> - -#define SBK_UNUSED(x) (void)(x); - -namespace Shiboken -{ - -/** -* It transforms a python sequence into two C variables, argc and argv. -* This function tries to find the application (script) name and put it into argv[0], if -* the application name can't be guessed, defaultAppName will be used. -* -* No memory is allocated is an error occur. -* -* \note argc must be a valid address. -* \note The argv array is allocated using new operator and each item is allocated using malloc. -* \returns True on sucess, false otherwise. -*/ -LIBSHIBOKEN_API bool listToArgcArgv(PyObject *argList, int *argc, char ***argv, const char *defaultAppName = nullptr); - -/** - * Convert a python sequence into a heap-allocated array of ints. - * - * \returns The newly allocated array or NULL in case of error or empty sequence. Check with PyErr_Occurred - * if it was successfull. - */ -LIBSHIBOKEN_API int *sequenceToIntArray(PyObject *obj, bool zeroTerminated = false); - -/** - * Creates and automatically deallocates C++ arrays. - */ -template<class T> -class AutoArrayPointer -{ - public: - AutoArrayPointer(const AutoArrayPointer &) = delete; - AutoArrayPointer(AutoArrayPointer &&) = delete; - AutoArrayPointer &operator=(const AutoArrayPointer &) = delete; - AutoArrayPointer &operator=(AutoArrayPointer &&) = delete; - - explicit AutoArrayPointer(int size) { data = new T[size]; } - T &operator[](int pos) { return data[pos]; } - operator T *() const { return data; } - ~AutoArrayPointer() { delete[] data; } - private: - T *data; -}; - -using ThreadId = unsigned long long; -LIBSHIBOKEN_API ThreadId currentThreadId(); -LIBSHIBOKEN_API ThreadId mainThreadId(); - -/** - * An utility function used to call PyErr_WarnEx with a formatted message. - */ -LIBSHIBOKEN_API int warning(PyObject *category, int stacklevel, const char *format, ...); - -struct LIBSHIBOKEN_API debugPyObject -{ - explicit debugPyObject(PyObject *o); - - PyObject *m_object; -}; - -struct LIBSHIBOKEN_API debugPyTypeObject -{ - explicit debugPyTypeObject(const PyTypeObject *o); - - const PyTypeObject *m_object; -}; - -LIBSHIBOKEN_API std::ostream &operator<<(std::ostream &str, const debugPyObject &o); -LIBSHIBOKEN_API std::ostream &operator<<(std::ostream &str, const debugPyTypeObject &o); - -} // namespace Shiboken - - -#endif // HELPER_H diff --git a/sources/shiboken2/libshiboken/pep384_issue33738.cpp b/sources/shiboken2/libshiboken/pep384_issue33738.cpp deleted file mode 100644 index c20edeefa..000000000 --- a/sources/shiboken2/libshiboken/pep384_issue33738.cpp +++ /dev/null @@ -1,121 +0,0 @@ -/**************************************************************************** -** -** Copyright (C) 2018 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$ -** -****************************************************************************/ - -// There is a bug in Python 3.6 that turned the Index_Check function -// into a macro without taking care of the limited API. -// This leads to the single problem that we don't have -// access to PyLong_Type's nb_index field which is no heap type. -// We cannot easily create this function by inheritance since it is -// not inherited. -// -// Simple solution: Create the structure and write such a function. -// Long term: Submit a patch to python.org . - -// Update: I did the long-term solution for python 3.7 in issue 33738. - -typedef struct { - /* Number implementations must check *both* - arguments for proper type and implement the necessary conversions - in the slot functions themselves. */ - - binaryfunc nb_add; - binaryfunc nb_subtract; - binaryfunc nb_multiply; - binaryfunc nb_remainder; - binaryfunc nb_divmod; - ternaryfunc nb_power; - unaryfunc nb_negative; - unaryfunc nb_positive; - unaryfunc nb_absolute; - inquiry nb_bool; - unaryfunc nb_invert; - binaryfunc nb_lshift; - binaryfunc nb_rshift; - binaryfunc nb_and; - binaryfunc nb_xor; - binaryfunc nb_or; - unaryfunc nb_int; - void *nb_reserved; /* the slot formerly known as nb_long */ - unaryfunc nb_float; - - binaryfunc nb_inplace_add; - binaryfunc nb_inplace_subtract; - binaryfunc nb_inplace_multiply; - binaryfunc nb_inplace_remainder; - ternaryfunc nb_inplace_power; - binaryfunc nb_inplace_lshift; - binaryfunc nb_inplace_rshift; - binaryfunc nb_inplace_and; - binaryfunc nb_inplace_xor; - binaryfunc nb_inplace_or; - - binaryfunc nb_floor_divide; - binaryfunc nb_true_divide; - binaryfunc nb_inplace_floor_divide; - binaryfunc nb_inplace_true_divide; - - unaryfunc nb_index; - - binaryfunc nb_matrix_multiply; - binaryfunc nb_inplace_matrix_multiply; -} PyNumberMethods; - -// temporary structure until we have a generator for the offsets -typedef struct _oldtypeobject { - PyVarObject ob_base; - void *X01; // const char *tp_name; - void *X02; // Py_ssize_t tp_basicsize; - void *X03; // Py_ssize_t tp_itemsize; - void *X04; // destructor tp_dealloc; - void *X05; // printfunc tp_print; - void *X06; // getattrfunc tp_getattr; - void *X07; // setattrfunc tp_setattr; - void *X08; // PyAsyncMethods *tp_as_async; - void *X09; // reprfunc tp_repr; - PyNumberMethods *tp_as_number; - -} PyOldTypeObject; - -int PyIndex_Check(PyObject *obj) -{ - PyOldTypeObject *type = reinterpret_cast<PyOldTypeObject *>(Py_TYPE(obj)); - return type->tp_as_number != NULL && - type->tp_as_number->nb_index != NULL; -} - diff --git a/sources/shiboken2/libshiboken/pep384impl.cpp b/sources/shiboken2/libshiboken/pep384impl.cpp deleted file mode 100644 index 4df9bc21d..000000000 --- a/sources/shiboken2/libshiboken/pep384impl.cpp +++ /dev/null @@ -1,847 +0,0 @@ -/**************************************************************************** -** -** Copyright (C) 2018 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$ -** -****************************************************************************/ - -#include "sbkpython.h" -#include "autodecref.h" -#include "sbkstaticstrings.h" -#include "sbkstaticstrings_p.h" -#include <stdlib.h> - - -extern "C" -{ - -/* - * The documentation is located in pep384impl_doc.rst - - * Here is the verification code for PyTypeObject. - * We create a type object and check if its fields - * appear at the right offsets. - */ -#ifdef Py_LIMITED_API - -#define make_dummy_int(x) (x * sizeof(void *)) -#define make_dummy(x) (reinterpret_cast<void *>(make_dummy_int(x))) - -static PyObject * -dummy_func(PyObject * /* self */, PyObject * /* args */) -{ - Py_RETURN_NONE; -} - -static struct PyMethodDef probe_methoddef[] = { - {"dummy", dummy_func, METH_NOARGS}, - {nullptr} -}; - -static PyGetSetDef probe_getseters[] = { - {nullptr} /* Sentinel */ -}; - -static PyMemberDef probe_members[] = { - {nullptr} /* Sentinel */ -}; - -#define probe_tp_dealloc make_dummy(1) -#define probe_tp_repr make_dummy(2) -#define probe_tp_call make_dummy(3) -#define probe_tp_getattro make_dummy(16) -#define probe_tp_setattro make_dummy(17) -#define probe_tp_str make_dummy(4) -#define probe_tp_traverse make_dummy(5) -#define probe_tp_clear make_dummy(6) -#define probe_tp_iternext make_dummy(7) -#define probe_tp_methods probe_methoddef -#define probe_tp_members probe_members -#define probe_tp_getset probe_getseters -#define probe_tp_descr_get make_dummy(10) -#define probe_tp_descr_set make_dummy(18) -#define probe_tp_init make_dummy(11) -#define probe_tp_alloc make_dummy(12) -#define probe_tp_new make_dummy(13) -#define probe_tp_free make_dummy(14) -#define probe_tp_is_gc make_dummy(15) - -#define probe_tp_name "type.probe" -#define probe_tp_basicsize make_dummy_int(42) - -static PyType_Slot typeprobe_slots[] = { - {Py_tp_dealloc, probe_tp_dealloc}, - {Py_tp_repr, probe_tp_repr}, - {Py_tp_call, probe_tp_call}, - {Py_tp_getattro, probe_tp_getattro}, - {Py_tp_setattro, probe_tp_setattro}, - {Py_tp_str, probe_tp_str}, - {Py_tp_traverse, probe_tp_traverse}, - {Py_tp_clear, probe_tp_clear}, - {Py_tp_iternext, probe_tp_iternext}, - {Py_tp_methods, probe_tp_methods}, - {Py_tp_members, probe_tp_members}, - {Py_tp_getset, probe_tp_getset}, - {Py_tp_descr_get, probe_tp_descr_get}, - {Py_tp_descr_set, probe_tp_descr_set}, - {Py_tp_init, probe_tp_init}, - {Py_tp_alloc, probe_tp_alloc}, - {Py_tp_new, probe_tp_new}, - {Py_tp_free, probe_tp_free}, - {Py_tp_is_gc, probe_tp_is_gc}, - {0, nullptr} -}; -static PyType_Spec typeprobe_spec = { - probe_tp_name, - probe_tp_basicsize, - 0, - Py_TPFLAGS_DEFAULT, - typeprobe_slots, -}; - -static void -check_PyTypeObject_valid() -{ - auto *obtype = reinterpret_cast<PyObject *>(&PyType_Type); - auto *probe_tp_base = reinterpret_cast<PyTypeObject *>( - PyObject_GetAttr(obtype, Shiboken::PyMagicName::base())); - auto *probe_tp_bases = PyObject_GetAttr(obtype, Shiboken::PyMagicName::bases()); - auto *check = reinterpret_cast<PyTypeObject *>( - PyType_FromSpecWithBases(&typeprobe_spec, probe_tp_bases)); - auto *typetype = reinterpret_cast<PyTypeObject *>(obtype); - PyObject *w = PyObject_GetAttr(obtype, Shiboken::PyMagicName::weakrefoffset()); - long probe_tp_weakrefoffset = PyLong_AsLong(w); - PyObject *d = PyObject_GetAttr(obtype, Shiboken::PyMagicName::dictoffset()); - long probe_tp_dictoffset = PyLong_AsLong(d); - PyObject *probe_tp_mro = PyObject_GetAttr(obtype, Shiboken::PyMagicName::mro()); - if (false - || strcmp(probe_tp_name, check->tp_name) != 0 - || probe_tp_basicsize != check->tp_basicsize - || probe_tp_dealloc != check->tp_dealloc - || probe_tp_repr != check->tp_repr - || probe_tp_call != check->tp_call - || probe_tp_getattro != check->tp_getattro - || probe_tp_setattro != check->tp_setattro - || probe_tp_str != check->tp_str - || probe_tp_traverse != check->tp_traverse - || probe_tp_clear != check->tp_clear - || probe_tp_weakrefoffset != typetype->tp_weaklistoffset - || probe_tp_iternext != check->tp_iternext - || probe_tp_methods != check->tp_methods - || probe_tp_getset != check->tp_getset - || probe_tp_base != typetype->tp_base - || !PyDict_Check(check->tp_dict) - || !PyDict_GetItemString(check->tp_dict, "dummy") - || probe_tp_descr_get != check->tp_descr_get - || probe_tp_descr_set != check->tp_descr_set - || probe_tp_dictoffset != typetype->tp_dictoffset - || probe_tp_init != check->tp_init - || probe_tp_alloc != check->tp_alloc - || probe_tp_new != check->tp_new - || probe_tp_free != check->tp_free - || probe_tp_is_gc != check->tp_is_gc - || probe_tp_bases != typetype->tp_bases - || probe_tp_mro != typetype->tp_mro - || Py_TPFLAGS_DEFAULT != (check->tp_flags & Py_TPFLAGS_DEFAULT)) - Py_FatalError("The structure of type objects has changed!"); - Py_DECREF(check); - Py_DECREF(probe_tp_base); - Py_DECREF(w); - Py_DECREF(d); - Py_DECREF(probe_tp_bases); - Py_DECREF(probe_tp_mro); -} - -#if PY_VERSION_HEX < PY_ISSUE33738_SOLVED -#include "pep384_issue33738.cpp" -#endif - -#endif // Py_LIMITED_API - -/***************************************************************************** - * - * Additional for object.h / class properties - * - */ -#ifdef Py_LIMITED_API -/* - * This implementation of `_PyType_Lookup` works for lookup in our classes. - * The implementation ignores all caching and versioning and is also - * less optimized. This is reduced from the Python implementation. - */ - -/* Internal API to look for a name through the MRO, bypassing the method cache. - This returns a borrowed reference, and might set an exception. - 'error' is set to: -1: error with exception; 1: error without exception; 0: ok */ -static PyObject * -find_name_in_mro(PyTypeObject *type, PyObject *name, int *error) -{ - Py_ssize_t i, n; - PyObject *mro, *res, *base, *dict; - - /* Look in tp_dict of types in MRO */ - mro = type->tp_mro; - - res = nullptr; - /* Keep a strong reference to mro because type->tp_mro can be replaced - during dict lookup, e.g. when comparing to non-string keys. */ - Py_INCREF(mro); - assert(PyTuple_Check(mro)); - n = PyTuple_GET_SIZE(mro); - for (i = 0; i < n; i++) { - base = PyTuple_GET_ITEM(mro, i); - assert(PyType_Check(base)); - dict = ((PyTypeObject *)base)->tp_dict; - assert(dict && PyDict_Check(dict)); - res = PyDict_GetItem(dict, name); - if (res != nullptr) - break; - if (PyErr_Occurred()) { - *error = -1; - goto done; - } - } - *error = 0; -done: - Py_DECREF(mro); - return res; -} - -/* Internal API to look for a name through the MRO. - This returns a borrowed reference, and doesn't set an exception! */ -PyObject * -_PepType_Lookup(PyTypeObject *type, PyObject *name) -{ - PyObject *res; - int error; - - /* We may end up clearing live exceptions below, so make sure it's ours. */ - assert(!PyErr_Occurred()); - - res = find_name_in_mro(type, name, &error); - /* Only put NULL results into cache if there was no error. */ - if (error) { - /* It's not ideal to clear the error condition, - but this function is documented as not setting - an exception, and I don't want to change that. - E.g., when PyType_Ready() can't proceed, it won't - set the "ready" flag, so future attempts to ready - the same type will call it again -- hopefully - in a context that propagates the exception out. - */ - if (error == -1) { - PyErr_Clear(); - } - return nullptr; - } - return res; -} - -#endif // Py_LIMITED_API - -/***************************************************************************** - * - * Support for unicodeobject.h - * - */ -#ifdef Py_LIMITED_API - -char * -_PepUnicode_AsString(PyObject *str) -{ - /* - * We need to keep the string alive but cannot borrow the Python object. - * Ugly easy way out: We re-code as an interned bytes string. This - * produces a pseudo-leak as long as there are new strings. - * Typically, this function is used for name strings, and the dict size - * will not grow so much. - */ -#define STRINGIFY(x) #x -#define TOSTRING(x) STRINGIFY(x) -#define AT __FILE__ ":" TOSTRING(__LINE__) - - static PyObject *cstring_dict = nullptr; - if (cstring_dict == nullptr) { - cstring_dict = PyDict_New(); - if (cstring_dict == nullptr) - Py_FatalError("Error in " AT); - } - PyObject *bytesStr = PyUnicode_AsEncodedString(str, "utf8", nullptr); - PyObject *entry = PyDict_GetItemWithError(cstring_dict, bytesStr); - if (entry == nullptr) { - int e = PyDict_SetItem(cstring_dict, bytesStr, bytesStr); - if (e != 0) - Py_FatalError("Error in " AT); - entry = bytesStr; - } - else - Py_DECREF(bytesStr); - return PyBytes_AsString(entry); -} -#endif // Py_LIMITED_API - -/***************************************************************************** - * - * Support for longobject.h - * - */ -#ifdef Py_LIMITED_API - -/* - * This is the original Python function _PyLong_AsInt() from longobject.c . - * We define it here because we are not allowed to use the function - * from Python with an underscore. - */ - -/* Get a C int from an int object or any object that has an __int__ - method. Return -1 and set an error if overflow occurs. */ - -int -_PepLong_AsInt(PyObject *obj) -{ - int overflow; - long result = PyLong_AsLongAndOverflow(obj, &overflow); - if (overflow || result > INT_MAX || result < INT_MIN) { - /* XXX: could be cute and give a different - message for overflow == -1 */ - PyErr_SetString(PyExc_OverflowError, - "Python int too large to convert to C int"); - return -1; - } - return int(result); -} -#endif // Py_LIMITED_API - -/***************************************************************************** - * - * Support for pydebug.h - * - */ -#ifdef Py_LIMITED_API - -static PyObject *sys_flags = nullptr; - -int -Pep_GetFlag(const char *name) -{ - static int initialized = 0; - int ret = -1; - - if (!initialized) { - sys_flags = PySys_GetObject("flags"); - // func gives no error if nullptr is returned and does not incref. - Py_XINCREF(sys_flags); - initialized = 1; - } - if (sys_flags != nullptr) { - PyObject *ob_ret = PyObject_GetAttrString(sys_flags, name); - if (ob_ret != nullptr) { - long long_ret = PyLong_AsLong(ob_ret); - Py_DECREF(ob_ret); - ret = (int) long_ret; - } - } - return ret; -} - -int -Pep_GetVerboseFlag() -{ - static int initialized = 0; - static int verbose_flag = -1; - - if (!initialized) { - verbose_flag = Pep_GetFlag("verbose"); - if (verbose_flag != -1) - initialized = 1; - } - return verbose_flag; -} -#endif // Py_LIMITED_API - -/***************************************************************************** - * - * Support for code.h - * - */ -#ifdef Py_LIMITED_API - -int -PepCode_Get(PepCodeObject *co, const char *name) -{ - PyObject *ob = reinterpret_cast<PyObject *>(co); - PyObject *ob_ret; - int ret = -1; - - ob_ret = PyObject_GetAttrString(ob, name); - if (ob_ret != nullptr) { - long long_ret = PyLong_AsLong(ob_ret); - Py_DECREF(ob_ret); - ret = (int) long_ret; - } - return ret; -} -#endif // Py_LIMITED_API - -/***************************************************************************** - * - * Support for datetime.h - * - */ -#ifdef Py_LIMITED_API - -datetime_struc *PyDateTimeAPI = nullptr; - -static PyTypeObject *dt_getCheck(const char *name) -{ - PyObject *op = PyObject_GetAttrString(PyDateTimeAPI->module, name); - if (op == nullptr) { - fprintf(stderr, "datetime.%s not found\n", name); - Py_FatalError("aborting"); - } - return reinterpret_cast<PyTypeObject *>(op); -} - -// init_DateTime is called earlier than our module init. -// We use the provided PyDateTime_IMPORT machinery. -datetime_struc * -init_DateTime(void) -{ - static int initialized = 0; - if (!initialized) { - PyDateTimeAPI = (datetime_struc *)malloc(sizeof(datetime_struc)); - if (PyDateTimeAPI == nullptr) - Py_FatalError("PyDateTimeAPI malloc error, aborting"); - PyDateTimeAPI->module = PyImport_ImportModule("datetime"); - if (PyDateTimeAPI->module == nullptr) - Py_FatalError("datetime module not found, aborting"); - PyDateTimeAPI->DateType = dt_getCheck("date"); - PyDateTimeAPI->DateTimeType = dt_getCheck("datetime"); - PyDateTimeAPI->TimeType = dt_getCheck("time"); - PyDateTimeAPI->DeltaType = dt_getCheck("timedelta"); - PyDateTimeAPI->TZInfoType = dt_getCheck("tzinfo"); - initialized = 1; - } - return PyDateTimeAPI; -} - -int -PyDateTime_Get(PyObject *ob, const char *name) -{ - PyObject *ob_ret; - int ret = -1; - - ob_ret = PyObject_GetAttrString(ob, name); - if (ob_ret != nullptr) { - long long_ret = PyLong_AsLong(ob_ret); - Py_DECREF(ob_ret); - ret = (int) long_ret; - } - return ret; -} - -PyObject * -PyDate_FromDate(int year, int month, int day) -{ - return PyObject_CallFunction((PyObject *)PyDateTimeAPI->DateType, - (char *)"(iii)", year, month, day); -} - -PyObject * -PyDateTime_FromDateAndTime(int year, int month, int day, - int hour, int min, int sec, int usec) -{ - return PyObject_CallFunction((PyObject *)PyDateTimeAPI->DateTimeType, - (char *)"(iiiiiii)", year, month, day, - hour, min, sec, usec); -} - -PyObject * -PyTime_FromTime(int hour, int min, int sec, int usec) -{ - return PyObject_CallFunction((PyObject *)PyDateTimeAPI->TimeType, - (char *)"(iiii)", hour, min, sec, usec); -} -#endif // Py_LIMITED_API - -/***************************************************************************** - * - * Support for pythonrun.h - * - */ -#ifdef Py_LIMITED_API - -// Flags are ignored in these simple helpers. -PyObject * -PyRun_String(const char *str, int start, PyObject *globals, PyObject *locals) -{ - PyObject *code = Py_CompileString(str, "pyscript", start); - PyObject *ret = nullptr; - - if (code != nullptr) { - ret = PyEval_EvalCode(code, globals, locals); - } - Py_XDECREF(code); - return ret; -} - -#endif // Py_LIMITED_API - -/***************************************************************************** - * - * Support for classobject.h - * - */ -#ifdef Py_LIMITED_API - -PyTypeObject *PepMethod_TypePtr = nullptr; - -static PyTypeObject *getMethodType(void) -{ - static const char prog[] = - "class _C:\n" - " def _m(self): pass\n" - "result = type(_C()._m)\n"; - return reinterpret_cast<PyTypeObject *>(PepRun_GetResult(prog)); -} - -// We have no access to PyMethod_New and must call types.MethodType, instead. -PyObject * -PyMethod_New(PyObject *func, PyObject *self) -{ - return PyObject_CallFunction((PyObject *)PepMethod_TypePtr, - (char *)"(OO)", func, self); -} - -PyObject * -PyMethod_Function(PyObject *im) -{ - PyObject *ret = PyObject_GetAttr(im, Shiboken::PyMagicName::func()); - - // We have to return a borrowed reference. - Py_DECREF(ret); - return ret; -} - -PyObject * -PyMethod_Self(PyObject *im) -{ - PyObject *ret = PyObject_GetAttr(im, Shiboken::PyMagicName::self()); - - // We have to return a borrowed reference. - // If we don't obey that here, then we get a test error! - Py_DECREF(ret); - return ret; -} -#endif // Py_LIMITED_API - -/***************************************************************************** - * - * Support for funcobject.h - * - */ -#ifdef Py_LIMITED_API - -PyObject * -PepFunction_Get(PyObject *ob, const char *name) -{ - PyObject *ret; - - // We have to return a borrowed reference. - ret = PyObject_GetAttrString(ob, name); - Py_XDECREF(ret); - return ret; -} - -// This became necessary after Windows was activated. - -PyTypeObject *PepFunction_TypePtr = nullptr; - -static PyTypeObject *getFunctionType(void) -{ - static const char prog[] = - "from types import FunctionType as result\n"; - return reinterpret_cast<PyTypeObject *>(PepRun_GetResult(prog)); -} -#endif // Py_LIMITED_API || Python 2 - -/***************************************************************************** - * - * Support for dictobject.h - * - */ - -/***************************************************************************** - * - * Extra support for signature.cpp - * - */ -#ifdef Py_LIMITED_API - -PyTypeObject *PepStaticMethod_TypePtr = nullptr; - -static PyTypeObject * -getStaticMethodType(void) -{ - // this works for Python 3, only - // "StaticMethodType = type(str.__dict__['maketrans'])\n"; - static const char prog[] = - "from xxsubtype import spamlist\n" - "result = type(spamlist.__dict__['staticmeth'])\n"; - return reinterpret_cast<PyTypeObject *>(PepRun_GetResult(prog)); -} - -typedef struct { - PyObject_HEAD - PyObject *sm_callable; - PyObject *sm_dict; -} staticmethod; - -PyObject * -PyStaticMethod_New(PyObject *callable) -{ - staticmethod *sm = (staticmethod *) - PyType_GenericAlloc(PepStaticMethod_TypePtr, 0); - if (sm != nullptr) { - Py_INCREF(callable); - sm->sm_callable = callable; - } - return reinterpret_cast<PyObject *>(sm); -} -#endif // Py_LIMITED_API - -/***************************************************************************** - * - * Common newly needed functions - * - */ - -// The introduction of heaptypes converted many type names to the -// dotted form, since PyType_FromSpec uses it to compute the module -// name. This function reverts this effect. -const char * -PepType_GetNameStr(PyTypeObject *type) -{ - const char *ret = type->tp_name; - const char *nodots = strrchr(ret, '.'); - if (nodots) - ret = nodots + 1; - return ret; -} - -/***************************************************************************** - * - * Newly introduced convenience functions - * - */ -#if PY_VERSION_HEX < 0x03070000 || defined(Py_LIMITED_API) - -PyObject * -PyImport_GetModule(PyObject *name) -{ - PyObject *m; - PyObject *modules = PyImport_GetModuleDict(); - if (modules == NULL) { - PyErr_SetString(PyExc_RuntimeError, "unable to get sys.modules"); - return NULL; - } - Py_INCREF(modules); - if (PyDict_CheckExact(modules)) { - m = PyDict_GetItemWithError(modules, name); /* borrowed */ - Py_XINCREF(m); - } - else { - m = PyObject_GetItem(modules, name); - if (m == NULL && PyErr_ExceptionMatches(PyExc_KeyError)) { - PyErr_Clear(); - } - } - Py_DECREF(modules); - return m; -} - -#endif // PY_VERSION_HEX < 0x03070000 || defined(Py_LIMITED_API) - -// 2020-06-16: For simplicity of creating arbitrary things, this function -// is now made public. - -PyObject * -PepRun_GetResult(const char *command) -{ - /* - * Evaluate a string and return the variable `result` - */ - PyObject *d, *v, *res; - - d = PyDict_New(); - if (d == nullptr - || PyDict_SetItem(d, Shiboken::PyMagicName::builtins(), PyEval_GetBuiltins()) < 0) { - return nullptr; - } - v = PyRun_String(command, Py_file_input, d, d); - res = v ? PyDict_GetItem(d, Shiboken::PyName::result()) : nullptr; - Py_XDECREF(v); - Py_DECREF(d); - return res; -} - -/***************************************************************************** - * - * Python 2 incompatibilities - * - * This is incompatibly implemented as macro in Python 2. - */ -#if PY_VERSION_HEX < 0x03000000 - -PyObject *PepMapping_Items(PyObject *o) -{ - return PyObject_CallMethod(o, const_cast<char *>("items"), NULL); -} - -#endif - -/***************************************************************************** - * - * Extra support for name mangling - * - */ - -#ifdef Py_LIMITED_API -// We keep these definitions local, because they don't work in Python 2. -# define PyUnicode_GET_LENGTH(op) PyUnicode_GetLength((PyObject *)(op)) -# define PyUnicode_READ_CHAR(u, i) PyUnicode_ReadChar((PyObject *)(u), (i)) -#endif // Py_LIMITED_API - -PyObject * -_Pep_PrivateMangle(PyObject *self, PyObject *name) -{ - /* - * Name mangling: __private becomes _classname__private. - * This function is modelled after _Py_Mangle, but is optimized - * a little for our purpose. - */ - if (PyUnicode_READ_CHAR(name, 0) != '_' || - PyUnicode_READ_CHAR(name, 1) != '_') { - Py_INCREF(name); - return name; - } - size_t nlen = PyUnicode_GET_LENGTH(name); - /* Don't mangle __id__ or names with dots. */ - if ((PyUnicode_READ_CHAR(name, nlen-1) == '_' && - PyUnicode_READ_CHAR(name, nlen-2) == '_') || - PyUnicode_FindChar(name, '.', 0, nlen, 1) != -1) { - Py_INCREF(name); - return name; - } - Shiboken::AutoDecRef privateobj(PyObject_GetAttr( - reinterpret_cast<PyObject *>(Py_TYPE(self)), Shiboken::PyMagicName::name())); -#ifndef Py_LIMITED_API - return _Py_Mangle(privateobj, name); -#else - // For some reason, _Py_Mangle is not in the Limited API. Why? - size_t plen = PyUnicode_GET_LENGTH(privateobj); - /* Strip leading underscores from class name */ - size_t ipriv = 0; - while (PyUnicode_READ_CHAR(privateobj, ipriv) == '_') - ipriv++; - if (ipriv == plen) { - Py_INCREF(name); - return name; /* Don't mangle if class is just underscores */ - } - plen -= ipriv; - - if (plen + nlen >= PY_SSIZE_T_MAX - 1) { - PyErr_SetString(PyExc_OverflowError, - "private identifier too large to be mangled"); - return nullptr; - } - size_t const amount = ipriv + 1 + plen + nlen; - size_t const big_stack = 1000; - wchar_t bigbuf[big_stack]; - wchar_t *resbuf = amount <= big_stack ? bigbuf : (wchar_t *)malloc(sizeof(wchar_t) * amount); - if (!resbuf) - return 0; - /* ident = "_" + priv[ipriv:] + ident # i.e. 1+plen+nlen bytes */ - resbuf[0] = '_'; - if (PyUnicode_AsWideChar(privateobj, resbuf + 1, ipriv + plen) < 0) - return 0; - if (PyUnicode_AsWideChar(name, resbuf + ipriv + plen + 1, nlen) < 0) - return 0; - PyObject *result = PyUnicode_FromWideChar(resbuf + ipriv, 1 + plen + nlen); - if (amount > big_stack) - free(resbuf); - return result; -#endif // else Py_LIMITED_API -} - -/***************************************************************************** - * - * Runtime support for Python 3.8 incompatibilities - * - */ - -int PepRuntime_38_flag = 0; - -static void -init_PepRuntime() -{ - // We expect a string of the form "\d\.\d+\." - const char *version = Py_GetVersion(); - if (version[0] < '3') - return; - if (std::atoi(version + 2) >= 8) - PepRuntime_38_flag = 1; -} - -/***************************************************************************** - * - * Module Initialization - * - */ - -void -Pep384_Init() -{ - init_PepRuntime(); -#ifdef Py_LIMITED_API - check_PyTypeObject_valid(); - Pep_GetVerboseFlag(); - PepMethod_TypePtr = getMethodType(); - PepFunction_TypePtr = getFunctionType(); - PepStaticMethod_TypePtr = getStaticMethodType(); -#endif // Py_LIMITED_API -} - -} // extern "C" diff --git a/sources/shiboken2/libshiboken/pep384impl.h b/sources/shiboken2/libshiboken/pep384impl.h deleted file mode 100644 index 07f4a913f..000000000 --- a/sources/shiboken2/libshiboken/pep384impl.h +++ /dev/null @@ -1,582 +0,0 @@ -/**************************************************************************** -** -** Copyright (C) 2018 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$ -** -****************************************************************************/ - -#ifndef PEP384IMPL_H -#define PEP384IMPL_H - -extern "C" -{ - -/***************************************************************************** - * - * RESOLVED: memoryobject.h - * - */ - -// Extracted into bufferprocs27.h -#ifdef Py_LIMITED_API -#include "bufferprocs_py37.h" -#endif - -/***************************************************************************** - * - * RESOLVED: object.h - * - */ -#ifdef Py_LIMITED_API -// Why the hell is this useful debugging function not allowed? -// BTW: When used, it breaks on Windows, intentionally! -LIBSHIBOKEN_API void _PyObject_Dump(PyObject *); -#endif - -/* - * There are a few structures that are needed, but cannot be used without - * breaking the API. We use some heuristics to get those fields anyway - * and validate that we really found them, see pep384impl.cpp . - */ - -#ifdef Py_LIMITED_API - -/* - * These are the type object fields that we use. - * We will verify that they never change. - * The unused fields are intentionally named as "void *Xnn" because - * the chance is smaller to forget to validate a field. - * When we need more fields, we replace it back and add it to the - * validation. - */ -typedef struct _typeobject { - PyVarObject ob_base; - const char *tp_name; - Py_ssize_t tp_basicsize; - void *X03; // Py_ssize_t tp_itemsize; - destructor tp_dealloc; - void *X05; // Py_ssize_t tp_vectorcall_offset; - void *X06; // getattrfunc tp_getattr; - void *X07; // setattrfunc tp_setattr; - void *X08; // PyAsyncMethods *tp_as_async; - reprfunc tp_repr; - void *X10; // PyNumberMethods *tp_as_number; - void *X11; // PySequenceMethods *tp_as_sequence; - void *X12; // PyMappingMethods *tp_as_mapping; - void *X13; // hashfunc tp_hash; - ternaryfunc tp_call; - reprfunc tp_str; - getattrofunc tp_getattro; - setattrofunc tp_setattro; - void *X18; // PyBufferProcs *tp_as_buffer; - unsigned long tp_flags; - void *X20; // const char *tp_doc; - traverseproc tp_traverse; - inquiry tp_clear; - void *X23; // richcmpfunc tp_richcompare; - Py_ssize_t tp_weaklistoffset; - void *X25; // getiterfunc tp_iter; - iternextfunc tp_iternext; - struct PyMethodDef *tp_methods; - struct PyMemberDef *tp_members; - struct PyGetSetDef *tp_getset; - struct _typeobject *tp_base; - PyObject *tp_dict; - descrgetfunc tp_descr_get; - descrsetfunc tp_descr_set; - Py_ssize_t tp_dictoffset; - initproc tp_init; - allocfunc tp_alloc; - newfunc tp_new; - freefunc tp_free; - inquiry tp_is_gc; /* For PyObject_IS_GC */ - PyObject *tp_bases; - PyObject *tp_mro; /* method resolution order */ - -} PyTypeObject; - -#ifndef PyObject_IS_GC -/* Test if an object has a GC head */ -#define PyObject_IS_GC(o) \ - (PyType_IS_GC(Py_TYPE(o)) \ - && (Py_TYPE(o)->tp_is_gc == NULL || Py_TYPE(o)->tp_is_gc(o))) -#endif - -// This was a macro error in the limited API from the beginning. -// It was fixed in Python master, but did make it only in Python 3.8 . -#define PY_ISSUE33738_SOLVED 0x03080000 -#if PY_VERSION_HEX < PY_ISSUE33738_SOLVED -#undef PyIndex_Check -LIBSHIBOKEN_API int PyIndex_Check(PyObject *obj); -#endif - -LIBSHIBOKEN_API PyObject *_PepType_Lookup(PyTypeObject *type, PyObject *name); - -#else // Py_LIMITED_API - -#define _PepType_Lookup(type, name) _PyType_Lookup(type, name) - -#endif // Py_LIMITED_API - -struct SbkObjectTypePrivate; -struct PySideQFlagsTypePrivate; -struct _SbkGenericTypePrivate; - -#define PepHeapType_SIZE \ - (reinterpret_cast<PyTypeObject *>(&PyType_Type)->tp_basicsize) - -#define _genericTypeExtender(etype) \ - (reinterpret_cast<char *>(etype) + PepHeapType_SIZE) - -#define PepType_SOTP(etype) \ - (*reinterpret_cast<SbkObjectTypePrivate **>(_genericTypeExtender(etype))) - -#define PepType_SETP(etype) \ - (reinterpret_cast<SbkEnumTypePrivate *>(_genericTypeExtender(etype))) - -#define PepType_PFTP(etype) \ - (reinterpret_cast<PySideQFlagsTypePrivate *>(_genericTypeExtender(etype))) - -#define PepType_SGTP(etype) \ - (reinterpret_cast<_SbkGenericTypePrivate *>(_genericTypeExtender(etype))) - -// functions used everywhere -LIBSHIBOKEN_API const char *PepType_GetNameStr(PyTypeObject *type); - -/***************************************************************************** - * - * RESOLVED: longobject.h - * - */ -#ifdef Py_LIMITED_API -LIBSHIBOKEN_API int _PepLong_AsInt(PyObject *); -#else -#define _PepLong_AsInt _PyLong_AsInt -#endif - -/***************************************************************************** - * - * RESOLVED: pydebug.h - * - */ -#ifdef Py_LIMITED_API -/* - * We have no direct access to Py_VerboseFlag because debugging is not - * supported. The python developers are partially a bit too rigorous. - * Instead, we compute the value and use a function call macro. - * Was before: extern LIBSHIBOKEN_API int Py_VerboseFlag; - */ -LIBSHIBOKEN_API int Pep_GetFlag(const char *name); -LIBSHIBOKEN_API int Pep_GetVerboseFlag(void); -#define Py_VerboseFlag Pep_GetVerboseFlag() -#endif - -/***************************************************************************** - * - * RESOLVED: unicodeobject.h - * - */ - -/////////////////////////////////////////////////////////////////////// -// -// PYSIDE-813: About The Length Of Unicode Objects -// ----------------------------------------------- -// -// In Python 2 and before Python 3.3, the macro PyUnicode_GET_SIZE -// worked fine and really like a macro. -// -// Meanwhile, the unicode objects have changed their layout very much, -// and the former cheap macro call has become a real function call -// that converts objects and needs PyMemory. -// -// That is not only inefficient, but also requires the GIL! -// This problem was visible by debug Python and qdatastream_test.py . -// It was found while fixing the refcount problem of PYSIDE-813 which -// needed a debug Python. -// - -// PyUnicode_GetSize is deprecated in favor of PyUnicode_GetLength. -#if PY_VERSION_HEX < 0x03000000 -#define PepUnicode_GetLength(op) PyUnicode_GetSize((PyObject *)(op)) -#else -#define PepUnicode_GetLength(op) PyUnicode_GetLength((PyObject *)(op)) -#endif - -#ifdef Py_LIMITED_API - -LIBSHIBOKEN_API char *_PepUnicode_AsString(PyObject *); - -#else -#define _PepUnicode_AsString PyUnicode_AsUTF8 -#endif - -/***************************************************************************** - * - * RESOLVED: bytesobject.h - * - */ -#ifdef Py_LIMITED_API -#define PyBytes_AS_STRING(op) PyBytes_AsString(op) -#define PyBytes_GET_SIZE(op) PyBytes_Size(op) -#endif - -/***************************************************************************** - * - * RESOLVED: floatobject.h - * - */ -#ifdef Py_LIMITED_API -#define PyFloat_AS_DOUBLE(op) PyFloat_AsDouble(op) -#endif - -/***************************************************************************** - * - * RESOLVED: tupleobject.h - * - */ -#ifdef Py_LIMITED_API -#define PyTuple_GET_ITEM(op, i) PyTuple_GetItem((PyObject *)op, i) -#define PyTuple_SET_ITEM(op, i, v) PyTuple_SetItem(op, i, v) -#define PyTuple_GET_SIZE(op) PyTuple_Size((PyObject *)op) -#endif - -/***************************************************************************** - * - * RESOLVED: listobject.h - * - */ -#ifdef Py_LIMITED_API -#define PyList_GET_ITEM(op, i) PyList_GetItem(op, i) -#define PyList_SET_ITEM(op, i, v) PyList_SetItem(op, i, v) -#define PyList_GET_SIZE(op) PyList_Size(op) -#endif - -/***************************************************************************** - * - * RESOLVED: dictobject.h - * - * PYSIDE-803, PYSIDE-813: We need PyDict_GetItemWithError in order to - * avoid the GIL. - */ -#if PY_VERSION_HEX < 0x03000000 -LIBSHIBOKEN_API PyObject *PyDict_GetItemWithError(PyObject *mp, PyObject *key); -#endif - -/***************************************************************************** - * - * RESOLVED: methodobject.h - * - */ - -#ifdef Py_LIMITED_API - -typedef struct _pycfunc PyCFunctionObject; -#define PyCFunction_GET_FUNCTION(func) PyCFunction_GetFunction((PyObject *)func) -#define PyCFunction_GET_SELF(func) PyCFunction_GetSelf((PyObject *)func) -#define PyCFunction_GET_FLAGS(func) PyCFunction_GetFlags((PyObject *)func) -#define PepCFunction_GET_NAMESTR(func) \ - _PepUnicode_AsString(PyObject_GetAttrString((PyObject *)func, "__name__")) -#else -#define PepCFunction_GET_NAMESTR(func) ((func)->m_ml->ml_name) -#endif - -/***************************************************************************** - * - * RESOLVED: pythonrun.h - * - */ -#ifdef Py_LIMITED_API -LIBSHIBOKEN_API PyObject *PyRun_String(const char *, int, PyObject *, PyObject *); -#endif - -/***************************************************************************** - * - * RESOLVED: abstract.h - * - */ -#ifdef Py_LIMITED_API - -// This definition breaks the limited API a little, because it re-enables the -// buffer functions. -// But this is no problem as we check it's validity for every version. - -#define PYTHON_BUFFER_VERSION_COMPATIBLE (PY_VERSION_HEX >= 0x03030000 && \ - PY_VERSION_HEX < 0x0309FFFF) -#if !PYTHON_BUFFER_VERSION_COMPATIBLE -# error Please check the buffer compatibility for this python version! -#endif - -typedef struct { - getbufferproc bf_getbuffer; - releasebufferproc bf_releasebuffer; -} PyBufferProcs; - -typedef struct _Pepbuffertype { - PyVarObject ob_base; - void *skip[17]; - PyBufferProcs *tp_as_buffer; -} PepBufferType; - -#define PepType_AS_BUFFER(type) \ - reinterpret_cast<PepBufferType *>(type)->tp_as_buffer - -#define PyObject_CheckBuffer(obj) \ - ((PepType_AS_BUFFER(Py_TYPE(obj)) != NULL) && \ - (PepType_AS_BUFFER(Py_TYPE(obj))->bf_getbuffer != NULL)) - -LIBSHIBOKEN_API int PyObject_GetBuffer(PyObject *ob, Pep_buffer *view, int flags); -LIBSHIBOKEN_API void PyBuffer_Release(Pep_buffer *view); - -#else - -#define Pep_buffer Py_buffer -#define PepType_AS_BUFFER(type) ((type)->tp_as_buffer) - -#endif /* Py_LIMITED_API */ - -/***************************************************************************** - * - * RESOLVED: funcobject.h - * - */ -#ifdef Py_LIMITED_API -typedef struct _func PyFunctionObject; - -extern LIBSHIBOKEN_API PyTypeObject *PepFunction_TypePtr; -LIBSHIBOKEN_API PyObject *PepFunction_Get(PyObject *, const char *); - -#define PyFunction_Check(op) (Py_TYPE(op) == PepFunction_TypePtr) -#define PyFunction_GET_CODE(func) PyFunction_GetCode(func) - -#define PyFunction_GetCode(func) PepFunction_Get((PyObject *)func, "__code__") -#define PepFunction_GetName(func) PepFunction_Get((PyObject *)func, "__name__") -#else -#define PepFunction_TypePtr (&PyFunction_Type) -#define PepFunction_GetName(func) (((PyFunctionObject *)func)->func_name) -#endif - -/***************************************************************************** - * - * RESOLVED: classobject.h - * - */ -#ifdef Py_LIMITED_API - -typedef struct _meth PyMethodObject; - -extern LIBSHIBOKEN_API PyTypeObject *PepMethod_TypePtr; - -LIBSHIBOKEN_API PyObject *PyMethod_New(PyObject *, PyObject *); -LIBSHIBOKEN_API PyObject *PyMethod_Function(PyObject *); -LIBSHIBOKEN_API PyObject *PyMethod_Self(PyObject *); - -#define PyMethod_Check(op) ((op)->ob_type == PepMethod_TypePtr) - -#define PyMethod_GET_SELF(op) PyMethod_Self(op) -#define PyMethod_GET_FUNCTION(op) PyMethod_Function(op) -#endif - -/***************************************************************************** - * - * RESOLVED: code.h - * - */ -#ifdef Py_LIMITED_API -/* Bytecode object */ - -// we have to grab the code object from python -typedef struct _code PepCodeObject; - -LIBSHIBOKEN_API int PepCode_Get(PepCodeObject *co, const char *name); - -# define PepCode_GET_FLAGS(o) PepCode_Get(o, "co_flags") -# define PepCode_GET_ARGCOUNT(o) PepCode_Get(o, "co_argcount") - -/* Masks for co_flags above */ -# define CO_OPTIMIZED 0x0001 -# define CO_NEWLOCALS 0x0002 -# define CO_VARARGS 0x0004 -# define CO_VARKEYWORDS 0x0008 -# define CO_NESTED 0x0010 -# define CO_GENERATOR 0x0020 - -#else - -# define PepCodeObject PyCodeObject -# define PepCode_GET_FLAGS(o) ((o)->co_flags) -# define PepCode_GET_ARGCOUNT(o) ((o)->co_argcount) - -#endif - -/***************************************************************************** - * - * RESOLVED: datetime.h - * - */ -#ifdef Py_LIMITED_API - -LIBSHIBOKEN_API int PyDateTime_Get(PyObject *ob, const char *name); - -#define PyDateTime_GetYear(o) PyDateTime_Get(o, "year") -#define PyDateTime_GetMonth(o) PyDateTime_Get(o, "month") -#define PyDateTime_GetDay(o) PyDateTime_Get(o, "day") -#define PyDateTime_GetHour(o) PyDateTime_Get(o, "hour") -#define PyDateTime_GetMinute(o) PyDateTime_Get(o, "minute") -#define PyDateTime_GetSecond(o) PyDateTime_Get(o, "second") -#define PyDateTime_GetMicrosecond(o) PyDateTime_Get(o, "microsecond") -#define PyDateTime_GetFold(o) PyDateTime_Get(o, "fold") - -#define PyDateTime_GET_YEAR(o) PyDateTime_GetYear(o) -#define PyDateTime_GET_MONTH(o) PyDateTime_GetMonth(o) -#define PyDateTime_GET_DAY(o) PyDateTime_GetDay(o) - -#define PyDateTime_DATE_GET_HOUR(o) PyDateTime_GetHour(o) -#define PyDateTime_DATE_GET_MINUTE(o) PyDateTime_GetMinute(o) -#define PyDateTime_DATE_GET_SECOND(o) PyDateTime_GetSecond(o) -#define PyDateTime_DATE_GET_MICROSECOND(o) PyDateTime_GetMicrosecond(o) -#define PyDateTime_DATE_GET_FOLD(o) PyDateTime_GetFold(o) - -#define PyDateTime_TIME_GET_HOUR(o) PyDateTime_GetHour(o) -#define PyDateTime_TIME_GET_MINUTE(o) PyDateTime_GetMinute(o) -#define PyDateTime_TIME_GET_SECOND(o) PyDateTime_GetSecond(o) -#define PyDateTime_TIME_GET_MICROSECOND(o) PyDateTime_GetMicrosecond(o) -#define PyDateTime_TIME_GET_FOLD(o) PyDateTime_GetFold(o) - -/* Define structure slightly similar to C API. */ -typedef struct { - PyObject *module; - /* type objects */ - PyTypeObject *DateType; - PyTypeObject *DateTimeType; - PyTypeObject *TimeType; - PyTypeObject *DeltaType; - PyTypeObject *TZInfoType; -} datetime_struc; - -LIBSHIBOKEN_API datetime_struc *init_DateTime(void); - -#define PyDateTime_IMPORT PyDateTimeAPI = init_DateTime() - -extern LIBSHIBOKEN_API datetime_struc *PyDateTimeAPI; - -#define PyDate_Check(op) PyObject_TypeCheck(op, PyDateTimeAPI->DateType) -#define PyDateTime_Check(op) PyObject_TypeCheck(op, PyDateTimeAPI->DateTimeType) -#define PyTime_Check(op) PyObject_TypeCheck(op, PyDateTimeAPI->TimeType) - -LIBSHIBOKEN_API PyObject *PyDate_FromDate(int year, int month, int day); -LIBSHIBOKEN_API PyObject *PyDateTime_FromDateAndTime( - int year, int month, int day, int hour, int min, int sec, int usec); -LIBSHIBOKEN_API PyObject *PyTime_FromTime( - int hour, int minute, int second, int usecond); - -#endif /* Py_LIMITED_API */ - -/***************************************************************************** - * - * Extra support for name mangling - * - */ - -// PYSIDE-772: This function supports the fix, but is not meant as public. -LIBSHIBOKEN_API PyObject *_Pep_PrivateMangle(PyObject *self, PyObject *name); - -/***************************************************************************** - * - * Extra support for signature.cpp - * - */ - -#ifdef Py_LIMITED_API -extern LIBSHIBOKEN_API PyTypeObject *PepStaticMethod_TypePtr; -LIBSHIBOKEN_API PyObject *PyStaticMethod_New(PyObject *callable); -#else -#define PepStaticMethod_TypePtr &PyStaticMethod_Type -#endif -// Although not PEP specific, we resolve this similar issue, here: -#if PY_VERSION_HEX < 0x03000000 -extern LIBSHIBOKEN_API PyTypeObject *PepMethodDescr_TypePtr; -#else -#define PepMethodDescr_TypePtr &PyMethodDescr_Type -#endif - -/***************************************************************************** - * - * Newly introduced convenience functions - * - * This is not defined if Py_LIMITED_API is defined. - */ -#if PY_VERSION_HEX < 0x03070000 || defined(Py_LIMITED_API) -LIBSHIBOKEN_API PyObject *PyImport_GetModule(PyObject *name); -#endif // PY_VERSION_HEX < 0x03070000 || defined(Py_LIMITED_API) - -// Evaluate a script and return the variable `result` -LIBSHIBOKEN_API PyObject *PepRun_GetResult(const char *command); - -/***************************************************************************** - * - * Python 2 incompatibilities - * - * This is incompatibly implemented as macro in Python 2. - */ -#if PY_VERSION_HEX < 0x03000000 -extern LIBSHIBOKEN_API PyObject *PepMapping_Items(PyObject *o); -#else -#define PepMapping_Items PyMapping_Items -#endif - -/***************************************************************************** - * - * Runtime support for Python 3.8 incompatibilities - * - */ - -#ifndef Py_TPFLAGS_METHOD_DESCRIPTOR -/* Objects behave like an unbound method */ -#define Py_TPFLAGS_METHOD_DESCRIPTOR (1UL << 17) -#endif - -extern LIBSHIBOKEN_API int PepRuntime_38_flag; - -/***************************************************************************** - * - * Module Initialization - * - */ - -LIBSHIBOKEN_API void Pep384_Init(void); - -} // extern "C" - -#endif // PEP384IMPL_H diff --git a/sources/shiboken2/libshiboken/pep384impl_doc.rst b/sources/shiboken2/libshiboken/pep384impl_doc.rst deleted file mode 100644 index d8ebdbe70..000000000 --- a/sources/shiboken2/libshiboken/pep384impl_doc.rst +++ /dev/null @@ -1,721 +0,0 @@ -**************************************** -The Transition To The Limited Python API -**************************************** - - -Foreword -======== - -Python supports a limited API that restricts access to certain structures. -Besides eliminating whole modules and all functions and macros which names -start with an -underscore, the most drastic restriction is the removal of normal type object -declarations. - -For details about the eliminated modules and functions, please see the -`PEP 384`_ page for reference. - - -.. _`PEP 384`: https://www.python.org/dev/peps/pep-0384/ - - - -Changed Modules -=============== - -All changed module's include files are listed with the changed functions here. -As a general rule, it was tried to keep the changes to a minimum diff. -Macros which are not available were changed to functions with the same name -if possible. Completely removed names ``Py{name}`` were re-implemented as ``Pep{name}``. - - -memoryobject.h --------------- - -The buffer protocol was completely removed. We redefined all the structures -and methods, because PySide uses that. This is an exception to the limited API -that we have to check ourselves. The code is extracted in bufferprocs_py37.h . -This is related to the following: - - -abstract.h ----------- - -This belongs to the buffer protocol like memoryobject.h . -As replacement for ``Py_buffer`` we defined ``Pep_buffer`` and several other -internal macros. - -The version is checked by hand, and the version number must be updated only -if the implementation does not change. Otherwise, we need to write version -dependent code paths. - -It is questionable if it is worthwhile to continue using the buffer protocol -or if we should try to get rid of ``Pep_buffer``, completely. - - -longobject.h ------------- - -``_PyLong_AsInt`` is not available. We defined a ``_PepLong_AsInt`` function, instead. -Maybe this should be replaced by ``PyLong_AsLong``. - - -pydebug.h ---------- - -We have no direct access to ``Py_VerboseFlag`` because debugging is not -supported. We redefined it as macro ``Py_VerboseFlag`` which calls ``Pep_VerboseFlag``. - - -unicodeobject.h ---------------- - -The macro ``PyUnicode_GET_SIZE`` was removed and replaced by ``PepUnicode_GetLength`` -which evaluates to ``PyUnicode_GetSize`` for Python 2 and ``PyUnicode_GetLength`` for Python 3. -Since Python 3.3, ``PyUnicode_GetSize`` would have the bad side effect of requiring the GIL! - -Function ``_PyUnicode_AsString`` is unavailable and was replaced by a macro -that calls ``_PepUnicode_AsString``. The implementation was a bit involved, -and it would be better to change the code and replace this function. - - -bytesobject.h -------------- - -The macros ``PyBytes_AS_STRING`` and ``PyBytes_GET_SIZE`` were redefined to call -the according functions. - - -floatobject.h -------------- - -``PyFloat_AS_DOUBLE`` now calls ``PyFloat_AsDouble``. - - -tupleobject.h -------------- - -``PyTuple_GET_ITEM``, ``PyTuple_SET_ITEM`` and ``PyTuple_GET_SIZE`` were redefined as -function calls. - - -listobject.h ------------- - -``PyList_GET_ITEM``, ``PyList_SET_ITEM`` and ``PyList_GET_SIZE`` were redefined as -function calls. - - -dictobject.h ------------- - -``PyDict_GetItem`` also exists in a ``PyDict_GetItemWithError`` version that does -not suppress errors. This suppression has the side effect of touching global -structures. This function exists in Python 2 only since Python 2.7.12 and has -a different name. We simply implemented the function. -Needed to avoid the GIL when accessing dictionaries. - - -methodobject.h --------------- - -``PyCFunction_GET_FUNCTION``, ``PyCFunction_GET_SELF`` and ``PyCFunction_GET_FLAGS`` -were redefined as function calls. - -Direct access to the methoddef structure is not available, and we defined -``PepCFunction_GET_NAMESTR`` as accessor for name strings. - - -pythonrun.h ------------ - -The simple function ``PyRun_String`` is not available. It was re-implemented -in a simplified version for the signature module. - - -funcobject.h ------------- - -The definitions of funcobject.h are completely missing, although there -are extra ``#ifdef`` conditional defines inside, too. This suggests that the exclusion -was unintended. - -We therefore redefined ``PyFunctionObject`` as an opaque type. - -The missing macro ``PyFunction_Check`` was defined, and the macro -``PyFunction_GET_CODE`` calls the according function. - -There is no equivalent for function name access, therefore we introduced -``PepFunction_GetName`` either as a function or as a macro. - -*TODO: We should fix funcobject.h* - - -classobject.h -------------- - -Classobject is also completely not imported, instead of defining an opaque type. - -We defined the missing functions ``PyMethod_New``, ``PyMethod_Function`` and -``PyMethod_Self`` and also redefined ``PyMethod_GET_SELF`` and -``PyMethod_GET_FUNCTION`` as calls to these functions. - -*TODO: We should fix classobject.h* - - -code.h ------- - -The whole code.c code is gone, although it may make sense to -define some minimum accessibility. This will be clarified on -`Python-Dev`_. We needed access to code objects and defined the missing -PepCode_GET_FLAGS and PepCode_GET_ARGCOUNT either as function or macro. -We further added the missing flags, although few are used: - -``CO_OPTIMIZED`` ``CO_NEWLOCALS`` ``CO_VARARGS`` ``CO_VARKEYWORDS`` ``CO_NESTED`` -``CO_GENERATOR`` - -*TODO: We should maybe fix code.h* - -.. _`Python-Dev`: https://mail.python.org/mailman/listinfo/python-dev - -datetime.h ----------- - -The DateTime module is explicitly not included in the limited API. -We defined all the needed functions but called them via Python instead -of direct call macros. This has a slight performance impact. - -The performance could be easily improved by providing an interface -that fetches all attributes at once, instead of going through the object -protocol every time. - -The re-defined macros and methods are:: - - PyDateTime_GET_YEAR - PyDateTime_GET_MONTH - PyDateTime_GET_DAY - PyDateTime_DATE_GET_HOUR - PyDateTime_DATE_GET_MINUTE - PyDateTime_DATE_GET_SECOND - PyDateTime_DATE_GET_MICROSECOND - PyDateTime_DATE_GET_FOLD - PyDateTime_TIME_GET_HOUR - PyDateTime_TIME_GET_MINUTE - PyDateTime_TIME_GET_SECOND - PyDateTime_TIME_GET_MICROSECOND - PyDateTime_TIME_GET_FOLD - - PyDate_Check - PyDateTime_Check - PyTime_Check - - PyDate_FromDate - PyDateTime_FromDateAndTime - PyTime_FromTime - -*XXX: We should maybe provide an optimized interface to datetime* - - -object.h --------- - -The file object.h contains the ``PyTypeObject`` structure, which is supposed -to be completely opaque. All access to types should be done through -``PyType_GetSlot`` calls. Due to bugs and deficiencies in the limited API -implementation, it was not possible to do that. Instead, we have defined -a simplified structure for ``PyTypeObject`` that has only the fields that -are used in PySide. - -We will explain later why and how this was done. Here is the reduced -structure:: - - typedef struct _typeobject { - PyVarObject ob_base; - const char *tp_name; - Py_ssize_t tp_basicsize; - void *X03; // Py_ssize_t tp_itemsize; - void *X04; // destructor tp_dealloc; - void *X05; // printfunc tp_print; - void *X06; // getattrfunc tp_getattr; - void *X07; // setattrfunc tp_setattr; - void *X08; // PyAsyncMethods *tp_as_async; - void *X09; // reprfunc tp_repr; - void *X10; // PyNumberMethods *tp_as_number; - void *X11; // PySequenceMethods *tp_as_sequence; - void *X12; // PyMappingMethods *tp_as_mapping; - void *X13; // hashfunc tp_hash; - ternaryfunc tp_call; - reprfunc tp_str; - void *X16; // getattrofunc tp_getattro; - void *X17; // setattrofunc tp_setattro; - void *X18; // PyBufferProcs *tp_as_buffer; - void *X19; // unsigned long tp_flags; - void *X20; // const char *tp_doc; - traverseproc tp_traverse; - inquiry tp_clear; - void *X23; // richcmpfunc tp_richcompare; - Py_ssize_t tp_weaklistoffset; - void *X25; // getiterfunc tp_iter; - void *X26; // iternextfunc tp_iternext; - struct PyMethodDef *tp_methods; - void *X28; // struct PyMemberDef *tp_members; - void *X29; // struct PyGetSetDef *tp_getset; - struct _typeobject *tp_base; - PyObject *tp_dict; - descrgetfunc tp_descr_get; - void *X33; // descrsetfunc tp_descr_set; - Py_ssize_t tp_dictoffset; - initproc tp_init; - allocfunc tp_alloc; - newfunc tp_new; - freefunc tp_free; - inquiry tp_is_gc; /* For PyObject_IS_GC */ - PyObject *tp_bases; - PyObject *tp_mro; /* method resolution order */ - } PyTypeObject; - -Function ``PyIndex_Check`` had to be defined in an unwanted way due to -a Python issue. See file pep384_issue33738.cpp . - -There are extension structures which have been isolated as special macros that -dynamically compute the right offsets of the extended type structures: - -* ``PepType_SOTP`` for ``SbkObjectTypePrivate`` -* ``PepType_SETP`` for ``SbkEnumTypePrivate`` -* ``PepType_PFTP`` for ``PySideQFlagsTypePrivate`` -* ``PepType_SGTP`` for ``_SbkGenericTypePrivate`` - -How these extension structures are used can best be seen by searching -``PepType_{four}`` in the source. - -Due to the new heaptype interface, the names of certain types contain -now the module name in the ``tp_name`` field. To have a compatible way -to access simple type names as C string, ``PepType_GetNameStr`` has been -written that skips over dotted name parts. - -Finally, the function ``_PyObject_Dump`` was excluded from the limited API. -This is a useful debugging aid that we always want to have available, -so it is added back, again. Anyway, we did not reimplement it, and so -Windows is not supported. -Therefore, a forgotten debugging call of this functions will break COIN. :-) - - -Using The New Type API -====================== - -After converting everything but the object.h file, we were a little -bit shocked: it suddenly was clear that we would have no more -access to type objects, and even more scary that all types which we -use have to be heap types, only! - -For PySide with its intense use of heap type extensions in various -flavors, the situation looked quite unsolvable. In the end, it was -nicely solved, but it took almost 3.5 months to get that right. - -Before we see how this is done, we will explain the differences -between the APIs and their consequences. - - -The Interface -------------- - -The old type API of Python knows static types and heap types. -Static types are written down as a declaration of a ``PyTypeObject`` -structure with all its fields filled in. Here is for example -the definition of the Python type ``object`` (Python 3.6):: - - PyTypeObject PyBaseObject_Type = { - PyVarObject_HEAD_INIT(&PyType_Type, 0) - "object", /* tp_name */ - sizeof(PyObject), /* tp_basicsize */ - 0, /* tp_itemsize */ - object_dealloc, /* tp_dealloc */ - 0, /* tp_print */ - 0, /* tp_getattr */ - 0, /* tp_setattr */ - 0, /* tp_reserved */ - object_repr, /* tp_repr */ - 0, /* tp_as_number */ - 0, /* tp_as_sequence */ - 0, /* tp_as_mapping */ - (hashfunc)_Py_HashPointer, /* tp_hash */ - 0, /* tp_call */ - object_str, /* tp_str */ - PyObject_GenericGetAttr, /* tp_getattro */ - PyObject_GenericSetAttr, /* tp_setattro */ - 0, /* tp_as_buffer */ - Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE, /* tp_flags */ - PyDoc_STR("object()\n--\n\nThe most base type"), /* tp_doc */ - 0, /* tp_traverse */ - 0, /* tp_clear */ - object_richcompare, /* tp_richcompare */ - 0, /* tp_weaklistoffset */ - 0, /* tp_iter */ - 0, /* tp_iternext */ - object_methods, /* tp_methods */ - 0, /* tp_members */ - object_getsets, /* tp_getset */ - 0, /* tp_base */ - 0, /* tp_dict */ - 0, /* tp_descr_get */ - 0, /* tp_descr_set */ - 0, /* tp_dictoffset */ - object_init, /* tp_init */ - PyType_GenericAlloc, /* tp_alloc */ - object_new, /* tp_new */ - PyObject_Del, /* tp_free */ - }; - -We can write the same structure in form of a ``PyType_Spec`` structure, -and there is even an incomplete tool *abitype.py* that does this conversion -for us. With a few corrections, the result looks like this:: - - static PyType_Slot PyBaseObject_Type_slots[] = { - {Py_tp_dealloc, (void *)object_dealloc}, - {Py_tp_repr, (void *)object_repr}, - {Py_tp_hash, (void *)_Py_HashPointer}, - {Py_tp_str, (void *)object_str}, - {Py_tp_getattro, (void *)PyObject_GenericGetAttr}, - {Py_tp_setattro, (void *)PyObject_GenericSetAttr}, - {Py_tp_richcompare, (void *)object_richcompare}, - {Py_tp_methods, (void *)object_methods}, - {Py_tp_getset, (void *)object_getsets}, - {Py_tp_init, (void *)object_init}, - {Py_tp_alloc, (void *)PyType_GenericAlloc}, - {Py_tp_new, (void *)object_new}, - {Py_tp_free, (void *)PyObject_Del}, - {0, 0}, - }; - static PyType_Spec PyBaseObject_Type_spec = { - "object", - sizeof(PyObject), - 0, - Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE, - PyBaseObject_Type_slots, - }; - -This new structure is almost compatible with the old one, but there -are some subtle differences. - -* The new types are generated in one step - -This seems to be no problem, but it was very much, due to the way the -types were built in PySide. Types were assembled piece by piece, and -finally the ``PyType_Ready`` function was called. - -With the new API, ``PyType_Ready`` is called already at the end of -``PyType_FromSpec``, and that meant that the logic of type creation became -completely turned upside down. - -* The new types are always heaptypes - -With the new type creation functions, it is no longer possible to -create "normal" types. Instead, they all have to be allocated on the -heap and garbage collected. The user should normally not recognize this. -But type creation is more constrained, and you cannot create a subtype -if the ``Py_TPFLAGS_BASETYPE`` is not set. This constraint was already -violated by PySide and needed a quite profound fix. - -* The new types always need a module - -While this is not a problem per se, the above new type spec will not create -a usable new type, but complain with:: - - DeprecationWarning: builtin type object has no __module__ attribute - -But there are more problems: - -* The new types have unexpected defaults - -When fields are empty, you would usually assume that they stay empty. -There are just a few corrections that ``PyType_Ready`` will do to a type. - -But there is the following clause in ``PyType_FromSpec`` that can give you -many headaches:: - - if (type->tp_dealloc == NULL) { - /* It's a heap type, so needs the heap types' dealloc. - subtype_dealloc will call the base type's tp_dealloc, if - necessary. */ - type->tp_dealloc = subtype_dealloc; - } - -In fact, before the move to the new API, the ``PyType_Ready`` function -filled empty ``tp_dealloc`` fields with ``object_dealloc``. And the code -that has been written with that in mind now becomes pretty wrong if suddenly -``subtype_dealloc`` is used. - -The way out was to explicitly provide an ``object_dealloc`` function. -This would then again impose a problem, because ``object_dealloc`` is not -public. Writing our own version is easy, but it again needs access to -type objects. But fortunately, we have broken this rule, already... - - -* The new types are only partially allocated - -The structures used in ``PyType_FromSpec`` are almost all allocated, -only the name field is static. This is no problem for types which are -statically created once. But if you want to parameterize things and -create multiple types with a single slots and spec definition, the name -field that is used for tp_name must be allocated dynamically. -This is misleading, since all the slots already are copies. - -* The new types don't support special offsets - -The special fields ``tp_weaklistoffset`` and ``tp_dictoffset`` are not supported -by ``PyType_FromSpec``. Unfortunately the documentation does not tell you -if you are allowed to set these fields manually after creating the type or not. -We finally did it and it worked, but we are not sure about correctness. - -See basewrapper.cpp function ``SbkObject_TypeF()`` as the only reference to -these fields in PySide. This single reference is absolutely necessary and -very important, since all derived types invisibly inherit these two fields. - - -Future Versions Of The Limited API -================================== - -As we have seen, the current version of the limited API does a bit of -cheating, because it uses parts of the data structure that should be -an opaque type. At the moment, this works fine because the data is -still way more compatible as it could be. - -But what if this is changed in the future? - -We know that the data structures are stable until Python 3.8 comes out. -Until then, the small bugs and omissions will hopefully all be solved. -Then it will be possible to replace the current small tricks by calls -to ``PyType_GetSlot`` in the way things should be. - -At the very moment when the current assumptions about the data structure -are no longer true, we will rewrite the direct attribute access with -calls to ``PyType_GetSlot``. After that, no more changes will be necessary. - - -Appendix A: The Transition To Simpler Types -=========================================== - -After all code had been converted to the limited API, there was a -remaining problem with the ``PyHeapTypeObject``. - -Why a problem? Well, all the type structures in shiboken use -special extra fields at the end of the heap type object. This -currently enforces extra knowledge at compile time about how large the -heap type object is. In a clean implementation, we would only use -the ``PyTypeObject`` itself and access the fields *behind* the type -by a pointer that is computed at runtime. - - -Restricted PyTypeObject ------------------------ - -Before we are going into details, let us motivate the existence of -the restricted ``PyTypeObject``: - -Originally, we wanted to use ``PyTypeObject`` as an opaque type and -restrict ourselves to only use the access function ``PyType_GetSlot``. -This function allows access to all fields which are supported by -the limited API. - -But this is a restriction, because we get no access to ``tp_dict``, -which we need to support the signature extension. But we can work -around that. - -The real restriction is that ``PyType_GetSlot`` only works for heap -types. This makes the function quite useless, because we have -no access to ``PyType_Type``, which is the most important type ``type`` -in Python. We need that for instance to compute the size of -``PyHeapTypeObject`` dynamically. - -With much effort, it is possible to clone ``PyType_Type`` as a heap -type. But due to a bug in the Pep 384 support, we need -access to the ``nb_index`` field of a normal type. Cloning does not -help because ``PyNumberMethods`` fields are *not* inherited. - -After we realized this dead end, we changed concept and did not -use ``PyType_GetSlot`` at all (except in function ``copyNumberMethods``), -but created a restricted ``PyTypeObject`` with only those fields -defined that are needed in PySide. - -Is this breakage of the limited API? I don't think so. A special -function runs on program startup that checks the correct position -of the fields of ``PyTypeObject``, although a change in those fields is -more than unlikely. -The really crucial thing is to no longer use ``PyHeapTypeObject`` -explicitly because that *does* change its layout over time. - - -Diversification ---------------- - -There were multiple ``Sbk{something}`` structures which all used a "d" field -for their private data. This made it not easy to find the right -fields when switching between objects and types:: - - struct LIBSHIBOKEN_API SbkObject - { - PyObject_HEAD - PyObject *ob_dict; - PyObject *weakreflist; - SbkObjectPrivate *d; - }; - - struct LIBSHIBOKEN_API SbkObjectType - { - PyHeapTypeObject super; - SbkObjectTypePrivate *d; - }; - -The first step was to rename the SbkObjectTypePrivate part from "d" to -"sotp". It was chosen to be short but easy to remember as abbreviation -of "SbkObjectTypePrivate", leading to:: - - struct LIBSHIBOKEN_API SbkObjectType - { - PyHeapTypeObject super; - SbkObjectTypePrivate *sotp; - }; - -After renaming, it was easier to do the following transformations. - - -Abstraction ------------ - -After renaming the type extension pointers to ``sotp``, I replaced -them by function-like macros which did the special access *behind* -the types, instead of those explicit fields. For instance, the -expression:: - - type->sotp->converter - -became:: - - PepType_SOTP(type)->converter - -The macro expansion can be seen here:: - - #define PepHeapType_SIZE \ - (reinterpret_cast<PyTypeObject *>(&PyType_Type)->tp_basicsize) - - #define _genericTypeExtender(etype) \ - (reinterpret_cast<char *>(etype) + PepHeapType_SIZE) - - #define PepType_SOTP(etype) \ - (*reinterpret_cast<SbkObjectTypePrivate **>(_genericTypeExtender(etype))) - -This looks complicated, but in the end there is only a single new -indirection via ``PyType_Type``, which happens at runtime. This is the -key to fulfil what Pep 384 wants to achieve: *No more version-dependent fields*. - - -Simplification --------------- - -After all type extension fields were replaced by macro calls, we -could remove the following version dependent re-definition of ``PyHeapTypeObject`` -:: - - typedef struct _pyheaptypeobject { - union { - PyTypeObject ht_type; - void *opaque[PY_HEAPTYPE_SIZE]; - }; - } PyHeapTypeObject; - -, and the version dependent structure:: - - struct LIBSHIBOKEN_API SbkObjectType - { - PyHeapTypeObject super; - SbkObjectTypePrivate *sotp; - }; - -could be replaced by the simplified:: - - struct LIBSHIBOKEN_API SbkObjectType - { - PyTypeObject type; - }; - -which is no longer version-dependent. -Note that we tried to replace the above struct directly by ``PyTypeObject``, -but that was too much. The distinction between ``SbkObjectType`` and -``PyTypeObject`` is still needed. - - -Appendix B: Verification Of PyTypeObject -======================================== - -We have introduced a limited PyTypeObject in the same place -as the original PyTypeObject, and now we need to prove that -we are allowed to do so. - -When using the limited API as intended, then types are completely -opaque, and access is only through ``PyType_FromSpec`` and (from -version 3.5 upwards) through ``PyType_GetSlot``. - -Python then uses all the slot definitions in the type description -and produces a regular heap type object. - - -Unused Information ------------------- - -We know many things about types that are not explicitly said, -but they are inherently clear: - -(a) The basic structure of a type is always the same, regardless - if it is a static type or a heap type. - -(b) types are evolving very slowly, and a field is never replaced - by another field with different semantics. - -Inherent rule (a) gives us the following information: If we calculate -the offsets of the basic fields, then this info is also usable for non-heap -types. - -The validation checks if rule (b) is still valid. - - -How it Works ------------- - -The basic idea of the validation is to produce a new type using -``PyType_FromSpec`` and to see where in the type structure these fields -show up. So we build a ``PyType_Slot`` structure with all the fields we -are using and make sure that these values are all unique in the -type. - -Most fields are not interrogated by ``PyType_FromSpec``, and so we -simply used some numeric value. Some fields are interpreted, like -``tp_members``. This field must really be a ``PyMemberDef``. And there are -``tp_base`` and ``tp_bases`` which have to be type objects and lists -thereof. It was easiest to not produce these fields from scratch -but use them from the ``type`` object ``PyType_Type``. - -Then one would think to write a function that searches the known -values in the opaque type structure. - -But we can do better and use optimistically the observation (b): -We simply use the restricted ``PyTypeObject`` structure and assume that -every field lands exactly where we are awaiting it. - -And that is the whole proof: If we find all the disjoint values at -the places where we expect them, then verification is done. - - -About ``tp_dict`` ------------------ - -One word about the ``tp_dict`` field: This field is a bit special in -the proof, since it does not appear in the spec and cannot easily -be checked by ``type.__dict__`` because that creates a *dictproxy* -object. So how do we prove that is really the right dict? - -We have to create that ``PyMethodDef`` structure anyway, and instead of -leaving it empty, we insert a dummy function. Then we ask the -``tp_dict`` field if it has the awaited object in it, and that's it! - -#EOT diff --git a/sources/shiboken2/libshiboken/python25compat.h b/sources/shiboken2/libshiboken/python25compat.h deleted file mode 100644 index b8a4950d9..000000000 --- a/sources/shiboken2/libshiboken/python25compat.h +++ /dev/null @@ -1,104 +0,0 @@ -/**************************************************************************** -** -** Copyright (C) 2016 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$ -** -****************************************************************************/ - -#ifndef PYTHON25COMPAT_H -#define PYTHON25COMPAT_H -#include "sbkpython.h" -#include <cstring> - -/* - *The #defines below were taken from Cython-generated code to allow shiboken to be used with python2.5. - * Maybe not all of these defines are useful to us, time will tell which ones are really needed or not. - */ - -#if PY_VERSION_HEX < 0x02060000 -#define Py_REFCNT(ob) (((PyObject *)(ob))->ob_refcnt) -#define Py_TYPE(ob) (((PyObject *)(ob))->ob_type) -#define Py_SIZE(ob) (((PyVarObject *)(ob))->ob_size) -#define PyVarObject_HEAD_INIT(type, size) \ - PyObject_HEAD_INIT(type) size, -#define PyType_Modified(t) - -typedef struct { - void *buf; - PyObject *obj; - Py_ssize_t len; - Py_ssize_t itemsize; - int readonly; - int ndim; - char *format; - Py_ssize_t *shape; - Py_ssize_t *strides; - Py_ssize_t *suboffsets; - void *internal; -} Py_buffer; - -#define PyBUF_SIMPLE 0 -#define PyBUF_WRITABLE 0x0001 -#define PyBUF_LOCK 0x0002 -#define PyBUF_FORMAT 0x0004 -#define PyBUF_ND 0x0008 -#define PyBUF_STRIDES (0x0010 | PyBUF_ND) -#define PyBUF_C_CONTIGUOUS (0x0020 | PyBUF_STRIDES) -#define PyBUF_F_CONTIGUOUS (0x0040 | PyBUF_STRIDES) -#define PyBUF_ANY_CONTIGUOUS (0x0080 | PyBUF_STRIDES) -#define PyBUF_INDIRECT (0x0100 | PyBUF_STRIDES) - -#define PyBytes_Check PyString_Check -#define PyBytes_FromString PyString_FromString -#define PyBytes_FromFormat PyString_FromFormat -#define PyBytes_FromStringAndSize PyString_FromStringAndSize -#define PyBytes_GET_SIZE PyString_GET_SIZE -#define PyBytes_AS_STRING PyString_AS_STRING -#define PyBytes_AsString PyString_AsString -#define PyBytes_Concat PyString_Concat -#define PyBytes_Size PyString_Size - -inline PyObject *PyUnicode_FromString(const char *s) -{ - std::size_t len = std::strlen(s); - return PyUnicode_DecodeUTF8(s, len, 0); -} - -#define PyLong_FromSize_t _PyLong_FromSize_t -#define PyLong_AsSsize_t _PyLong_AsSsize_t - -#endif - -#endif diff --git a/sources/shiboken2/libshiboken/qapp_macro.cpp b/sources/shiboken2/libshiboken/qapp_macro.cpp deleted file mode 100644 index 3ef3a51c6..000000000 --- a/sources/shiboken2/libshiboken/qapp_macro.cpp +++ /dev/null @@ -1,100 +0,0 @@ -/**************************************************************************** -** -** Copyright (C) 2017 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$ -** -****************************************************************************/ - -#include "basewrapper.h" -#include "autodecref.h" - -extern "C" -{ - -#include "qapp_macro.h" - -//////////////////////////////////////////////////////////////////////////// -// -// Support for the qApp macro. -// -// qApp is a macro in Qt5. In Python, we simulate that a little by a -// variable that monitors Q*Application.instance(). -// This variable is also able to destroy the app by qApp.shutdown(). -// - -static PyObject *qApp_var = nullptr; -static PyObject *qApp_content = nullptr; - -static PyObject * -monitor_qApp_var(PyObject *qApp) -{ - static bool init_done; - static PyObject *builtins = PyEval_GetBuiltins(); - - if (!init_done) { - qApp_var = Py_BuildValue("s", "qApp"); - if (qApp_var == nullptr) - return nullptr; - // This is a borrowed reference - Py_INCREF(builtins); - init_done = true; - } - - if (PyDict_SetItem(builtins, qApp_var, qApp) < 0) - return nullptr; - qApp_content = qApp; - Py_INCREF(qApp); - return qApp; -} - -PyObject * -MakeQAppWrapper(PyTypeObject *type) -{ - if (type == nullptr) - type = Py_TYPE(Py_None); - if (!(type == Py_TYPE(Py_None) || Py_TYPE(qApp_content) == Py_TYPE(Py_None))) { - const char *res_name = PepType_GetNameStr(Py_TYPE(qApp_content)); - const char *type_name = PepType_GetNameStr(type); - PyErr_Format(PyExc_RuntimeError, "Please destroy the %s singleton before" - " creating a new %s instance.", res_name, type_name); - return nullptr; - } - PyObject *self = type != Py_TYPE(Py_None) ? PyObject_New(PyObject, type) : Py_None; - return monitor_qApp_var(self); -} - -} //extern "C" - -// end of module diff --git a/sources/shiboken2/libshiboken/qapp_macro.h b/sources/shiboken2/libshiboken/qapp_macro.h deleted file mode 100644 index 9abd17c17..000000000 --- a/sources/shiboken2/libshiboken/qapp_macro.h +++ /dev/null @@ -1,52 +0,0 @@ -/**************************************************************************** -** -** Copyright (C) 2017 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$ -** -****************************************************************************/ - -#ifndef QAPP_MACRO_H -#define QAPP_MACRO_H - -#include "sbkpython.h" - -extern "C" -{ - -LIBSHIBOKEN_API PyObject *MakeQAppWrapper(PyTypeObject *type); - -} // extern "C" - -#endif // QAPP_MACRO_H diff --git a/sources/shiboken2/libshiboken/qt_attribution.json b/sources/shiboken2/libshiboken/qt_attribution.json deleted file mode 100644 index 1efc24a97..000000000 --- a/sources/shiboken2/libshiboken/qt_attribution.json +++ /dev/null @@ -1,12 +0,0 @@ -{ - "Id": "python", - "Name": "Python", - "QDocModule": "QtForPython", - "QtUsage": "Used for Qt for Python in the signature extension.", - "Description": "Qt for Python is an add-on for Python. The libshiboken packages of PySide uses certain parts of the source files (bufferprocs_py37.cpp, bufferprocs_py37.h). See the folder sources/shiboken2/libshiboken .", - "Homepage": "http://www.python.org/", - "Version": "3.7.0", - "License": "PSF LICENSE AGREEMENT FOR PYTHON 3.7.0", - "LicenseFile": "bufferprocs_py37.h", - "Copyright": "© Copyright 2001-2018, Python Software Foundation." -} diff --git a/sources/shiboken2/libshiboken/sbkarrayconverter.cpp b/sources/shiboken2/libshiboken/sbkarrayconverter.cpp deleted file mode 100644 index d94d03b34..000000000 --- a/sources/shiboken2/libshiboken/sbkarrayconverter.cpp +++ /dev/null @@ -1,285 +0,0 @@ -/**************************************************************************** -** -** Copyright (C) 2017 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$ -** -****************************************************************************/ - -#include "sbkarrayconverter.h" -#include "sbkarrayconverter_p.h" -#include "helper.h" -#include "sbkconverter.h" -#include "sbkconverter_p.h" - -#include <longobject.h> -#include <floatobject.h> - -#include <algorithm> - -static SbkArrayConverter *ArrayTypeConverters[Shiboken::Conversions::SBK_ARRAY_IDX_SIZE] [2] = {}; - -namespace Shiboken { -namespace Conversions { - -// Check whether Predicate is true for all elements of a sequence -template <class Predicate> -static bool sequenceAllOf(PyObject *pyIn, Predicate p) -{ - const Py_ssize_t size = PySequence_Size(pyIn); - for (Py_ssize_t i = 0; i < size; ++i) { - PyObject *item = PySequence_GetItem(pyIn, i); - const bool ok = p(item); - Py_XDECREF(item); - if (!ok) - return false; - } - return true; -} - -// Convert a sequence to output iterator -template <class T, class Converter> -inline void convertPySequence(PyObject *pyIn, Converter c, T *out) -{ - const Py_ssize_t size = PySequence_Size(pyIn); - for (Py_ssize_t i = 0; i < size; ++i) { - PyObject *item = PySequence_GetItem(pyIn, i); - *out++ = c(item); - Py_XDECREF(item); - } -} - -// Internal, for usage by numpy -SbkArrayConverter *createArrayConverter(IsArrayConvertibleToCppFunc toCppCheckFunc) -{ - auto *result = new SbkArrayConverter; - result->toCppConversions.push_back(toCppCheckFunc); - return result; -} - -static PythonToCppFunc unimplementedArrayCheck(PyObject *, int, int) -{ - warning(PyExc_RuntimeWarning, 0, "SbkConverter: Unimplemented C++ array type."); - return nullptr; -} - -SbkArrayConverter *unimplementedArrayConverter() -{ - static SbkArrayConverter *result = createArrayConverter(unimplementedArrayCheck); - return result; -} - -// Integers - -static inline bool intCheck(PyObject *pyIn) -{ - return PyLong_Check(pyIn); -} - -static short toShort(PyObject *pyIn) { return short(PyLong_AsLong(pyIn)); } - -static void sequenceToCppShortArray(PyObject *pyIn, void *cppOut) -{ - auto *handle = reinterpret_cast<ArrayHandle<short> *>(cppOut); - handle->allocate(PySequence_Size(pyIn)); - convertPySequence(pyIn, toShort, handle->data()); -} - -static inline bool sequenceSizeCheck(PyObject *pyIn, int expectedSize = -1) -{ - if (expectedSize >= 0) { - const int size = int(PySequence_Size(pyIn)); - if (size < expectedSize) { - warning(PyExc_RuntimeWarning, 0, "A sequence of size %d was passed to a function that expects %d.", - size, expectedSize); - return false; - } - } - return true; -} - -static inline bool intArrayCheck(PyObject *pyIn, int expectedSize = -1) -{ - return PySequence_Check(pyIn) && sequenceAllOf(pyIn, intCheck) - && sequenceSizeCheck(pyIn, expectedSize); -} - -static PythonToCppFunc sequenceToCppShortArrayCheck(PyObject *pyIn, int dim1, int /* dim2 */) -{ - return intArrayCheck(pyIn, dim1) ? sequenceToCppShortArray : nullptr; -} - -static short toUnsignedShort(PyObject *pyIn) { return static_cast<unsigned short>(PyLong_AsUnsignedLong(pyIn)); } - -static void sequenceToCppUnsignedShortArray(PyObject *pyIn, void *cppOut) -{ - auto *handle = reinterpret_cast<ArrayHandle<unsigned short> *>(cppOut); - handle->allocate(PySequence_Size(pyIn)); - convertPySequence(pyIn, toUnsignedShort, handle->data()); -} - -static PythonToCppFunc sequenceToCppUnsignedShortArrayCheck(PyObject *pyIn, int dim1, int /* dim2 */) -{ - return intArrayCheck(pyIn, dim1) ? sequenceToCppUnsignedShortArray : nullptr; -} - -static void sequenceToCppIntArray(PyObject *pyIn, void *cppOut) -{ - auto *handle = reinterpret_cast<ArrayHandle<int> *>(cppOut); - handle->allocate(PySequence_Size(pyIn)); - convertPySequence(pyIn, _PepLong_AsInt, handle->data()); -} - -static PythonToCppFunc sequenceToCppIntArrayCheck(PyObject *pyIn, int dim1, int /* dim2 */) -{ - return intArrayCheck(pyIn, dim1) ? sequenceToCppIntArray : nullptr; -} - -static void sequenceToCppUnsignedArray(PyObject *pyIn, void *cppOut) -{ - auto *handle = reinterpret_cast<ArrayHandle<unsigned> *>(cppOut); - handle->allocate(PySequence_Size(pyIn)); - convertPySequence(pyIn, PyLong_AsUnsignedLong, handle->data()); -} - -static PythonToCppFunc sequenceToCppUnsignedArrayCheck(PyObject *pyIn, int dim1, int /* dim2 */) -{ - return intArrayCheck(pyIn, dim1) ? sequenceToCppUnsignedArray : nullptr; -} - -static void sequenceToCppLongLongArray(PyObject *pyIn, void *cppOut) -{ - auto *handle = reinterpret_cast<ArrayHandle<long long> *>(cppOut); - handle->allocate(PySequence_Size(pyIn)); - convertPySequence(pyIn, PyLong_AsLongLong, handle->data()); -} - -static PythonToCppFunc sequenceToCppLongLongArrayCheck(PyObject *pyIn, int dim1, int /* dim2 */) -{ - return intArrayCheck(pyIn, dim1) ? sequenceToCppLongLongArray : nullptr; -} - -static void sequenceToCppUnsignedLongLongArray(PyObject *pyIn, void *cppOut) -{ - auto *handle = reinterpret_cast<ArrayHandle<unsigned long long> *>(cppOut); - handle->allocate(PySequence_Size(pyIn)); - convertPySequence(pyIn, PyLong_AsUnsignedLongLong, handle->data()); -} - -static PythonToCppFunc sequenceToCppUnsignedLongLongArrayCheck(PyObject *pyIn, int dim1, int /* dim2 */) -{ - return intArrayCheck(pyIn, dim1) ? sequenceToCppUnsignedLongLongArray : nullptr; -} - -// Float - -static inline bool floatCheck(PyObject *pyIn) { return PyFloat_Check(pyIn); } - -static inline bool floatArrayCheck(PyObject *pyIn, int expectedSize = -1) -{ - return PySequence_Check(pyIn) && sequenceAllOf(pyIn, floatCheck) - && sequenceSizeCheck(pyIn, expectedSize); -} - -static void sequenceToCppDoubleArray(PyObject *pyIn, void *cppOut) -{ - auto *handle = reinterpret_cast<ArrayHandle<double> *>(cppOut); - handle->allocate(PySequence_Size(pyIn)); - convertPySequence(pyIn, PyFloat_AsDouble, handle->data()); -} - -static inline float pyToFloat(PyObject *pyIn) { return float(PyFloat_AsDouble(pyIn)); } - -static void sequenceToCppFloatArray(PyObject *pyIn, void *cppOut) -{ - auto *handle = reinterpret_cast<ArrayHandle<float> *>(cppOut); - handle->allocate(PySequence_Size(pyIn)); - convertPySequence(pyIn, pyToFloat, handle->data()); -} - -static PythonToCppFunc sequenceToCppFloatArrayCheck(PyObject *pyIn, int dim1, int /* dim2 */) -{ - return floatArrayCheck(pyIn, dim1) ? sequenceToCppFloatArray : nullptr; -} - -static PythonToCppFunc sequenceToCppDoubleArrayCheck(PyObject *pyIn, int dim1, int /* dim2 */) -{ - return floatArrayCheck(pyIn, dim1) ? sequenceToCppDoubleArray : nullptr; -} - -#ifdef HAVE_NUMPY -void initNumPyArrayConverters(); -#endif - -void initArrayConverters() -{ - SbkArrayConverter **start = &ArrayTypeConverters[0][0]; - std::fill(start, start + sizeof(ArrayTypeConverters) / sizeof(ArrayTypeConverters[0][0]), nullptr); - // Populate 1-dimensional sequence converters - ArrayTypeConverters[SBK_DOUBLE_ARRAY_IDX][0] = - createArrayConverter(sequenceToCppDoubleArrayCheck); - ArrayTypeConverters[SBK_FLOAT_ARRAY_IDX][0] = - createArrayConverter(sequenceToCppFloatArrayCheck); - ArrayTypeConverters[SBK_SHORT_ARRAY_IDX][0] = - createArrayConverter(sequenceToCppShortArrayCheck); - ArrayTypeConverters[SBK_UNSIGNEDSHORT_ARRAY_IDX][0] = - createArrayConverter(sequenceToCppUnsignedShortArrayCheck); - ArrayTypeConverters[SBK_INT_ARRAY_IDX][0] = - createArrayConverter(sequenceToCppIntArrayCheck); - ArrayTypeConverters[SBK_UNSIGNEDINT_ARRAY_IDX][0] = - createArrayConverter(sequenceToCppUnsignedArrayCheck); - ArrayTypeConverters[SBK_LONGLONG_ARRAY_IDX][0] = - createArrayConverter(sequenceToCppLongLongArrayCheck); - ArrayTypeConverters[SBK_UNSIGNEDLONGLONG_ARRAY_IDX][0] = - createArrayConverter(sequenceToCppUnsignedLongLongArrayCheck); - -#ifdef HAVE_NUMPY - initNumPyArrayConverters(); -#endif -} - -SbkArrayConverter *arrayTypeConverter(int index, int dimension) -{ - SbkArrayConverter *c = ArrayTypeConverters[index][dimension - 1]; - return c ? c : unimplementedArrayConverter(); -} - -// Internal, for usage by numpy -void setArrayTypeConverter(int index, int dimension, SbkArrayConverter *c) -{ - ArrayTypeConverters[index][dimension - 1] = c; -} - -} // namespace Conversions -} // namespace Shiboken diff --git a/sources/shiboken2/libshiboken/sbkarrayconverter.h b/sources/shiboken2/libshiboken/sbkarrayconverter.h deleted file mode 100644 index 84cb2f57f..000000000 --- a/sources/shiboken2/libshiboken/sbkarrayconverter.h +++ /dev/null @@ -1,174 +0,0 @@ -/**************************************************************************** -** -** Copyright (C) 2017 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$ -** -****************************************************************************/ - -#ifndef SBKARRAYCONVERTERS_H -#define SBKARRAYCONVERTERS_H - -#include "sbkpython.h" -#include "shibokenmacros.h" - -extern "C" { -struct SbkArrayConverter; -} - -namespace Shiboken { -namespace Conversions { - -enum : int { - SBK_UNIMPLEMENTED_ARRAY_IDX, - SBK_DOUBLE_ARRAY_IDX, - SBK_FLOAT_ARRAY_IDX, - SBK_SHORT_ARRAY_IDX, - SBK_UNSIGNEDSHORT_ARRAY_IDX, - SBK_INT_ARRAY_IDX, - SBK_UNSIGNEDINT_ARRAY_IDX, - SBK_LONGLONG_ARRAY_IDX, - SBK_UNSIGNEDLONGLONG_ARRAY_IDX, - SBK_ARRAY_IDX_SIZE -}; - -/** - * ArrayHandle is the type expected by shiboken2's array converter - * functions. It provides access to array data which it may own - * (in the case of conversions from PySequence) or a flat pointer - * to internal data (in the case of array modules like numpy). - */ - -template <class T> -class ArrayHandle -{ -public: - ArrayHandle(const ArrayHandle &) = delete; - ArrayHandle& operator=(const ArrayHandle &) = delete; - ArrayHandle(ArrayHandle &&) = delete; - ArrayHandle& operator=(ArrayHandle &&) = delete; - - ArrayHandle() = default; - ~ArrayHandle() { destroy(); } - - void allocate(Py_ssize_t size); - void setData(T *d, size_t size); - - size_t size() const { return m_size; } - T *data() const { return m_data; } - operator T *() const { return m_data; } - -private: - void destroy(); - - T *m_data = nullptr; - Py_ssize_t m_size = 0; - bool m_owned = false; -}; - -/** - * Similar to ArrayHandle for fixed size 2 dimensional arrays. - * columns is the size of the last dimension - * It only has a setData() methods since it will be used for numpy only. - */ - -template <class T, int columns> -class Array2Handle -{ -public: - typedef T RowType[columns]; - - Array2Handle() = default; - - operator RowType *() const { return m_rows; } - - void setData(RowType *d) { m_rows = d; } - -private: - RowType *m_rows = nullptr; -}; - -/// Returns the converter for an array type. -LIBSHIBOKEN_API SbkArrayConverter *arrayTypeConverter(int index, int dimension = 1); - -template <class T> -struct ArrayTypeIndex{ - enum : int { index = SBK_UNIMPLEMENTED_ARRAY_IDX }; -}; - -template <> struct ArrayTypeIndex<double> { enum : int { index = SBK_DOUBLE_ARRAY_IDX }; }; -template <> struct ArrayTypeIndex<float> { enum : int { index = SBK_FLOAT_ARRAY_IDX };}; -template <> struct ArrayTypeIndex<short> { enum : int { index = SBK_SHORT_ARRAY_IDX };}; -template <> struct ArrayTypeIndex<unsigned short> { enum : int { index = SBK_UNSIGNEDSHORT_ARRAY_IDX };}; -template <> struct ArrayTypeIndex<int> { enum : int { index = SBK_INT_ARRAY_IDX };}; -template <> struct ArrayTypeIndex<unsigned> { enum : int { index = SBK_UNSIGNEDINT_ARRAY_IDX };}; -template <> struct ArrayTypeIndex<long long> { enum : int { index = SBK_LONGLONG_ARRAY_IDX };}; -template <> struct ArrayTypeIndex<unsigned long long> { enum : int { index = SBK_UNSIGNEDLONGLONG_ARRAY_IDX };}; - -template<typename T> SbkArrayConverter *ArrayTypeConverter(int dimension) -{ return arrayTypeConverter(ArrayTypeIndex<T>::index, dimension); } - -// ArrayHandle methods -template<class T> -void ArrayHandle<T>::allocate(Py_ssize_t size) -{ - destroy(); - m_data = new T[size]; - m_size = size; - m_owned = true; -} - -template<class T> -void ArrayHandle<T>::setData(T *d, size_t size) -{ - destroy(); - m_data = d; - m_size = size; - m_owned = false; -} - -template<class T> -void ArrayHandle<T>::destroy() -{ - if (m_owned) - delete [] m_data; - m_data = nullptr; - m_size = 0; - m_owned = false; -} - -} // namespace Conversions -} // namespace Shiboken - -#endif // SBKARRAYCONVERTERS_H diff --git a/sources/shiboken2/libshiboken/sbkarrayconverter_p.h b/sources/shiboken2/libshiboken/sbkarrayconverter_p.h deleted file mode 100644 index a7b46702b..000000000 --- a/sources/shiboken2/libshiboken/sbkarrayconverter_p.h +++ /dev/null @@ -1,62 +0,0 @@ -/**************************************************************************** -** -** Copyright (C) 2017 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$ -** -****************************************************************************/ - -#ifndef SBKARRAYCONVERTER_P_H -#define SBKARRAYCONVERTER_P_H - -#include "sbkconverter_p.h" -#include <vector> - -extern "C" -{ - -typedef PythonToCppFunc (*IsArrayConvertibleToCppFunc)(PyObject *, int dim1, int dim2); -/** - * \internal - * Private structure of SbkArrayConverter. - */ - -struct SbkArrayConverter -{ - std::vector<IsArrayConvertibleToCppFunc> toCppConversions; -}; - -} // extern "C" - -#endif // SBKARRAYCONVERTER_P_H diff --git a/sources/shiboken2/libshiboken/sbkconverter.cpp b/sources/shiboken2/libshiboken/sbkconverter.cpp deleted file mode 100644 index 29eb19715..000000000 --- a/sources/shiboken2/libshiboken/sbkconverter.cpp +++ /dev/null @@ -1,597 +0,0 @@ -/**************************************************************************** -** -** Copyright (C) 2016 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$ -** -****************************************************************************/ - -#include "sbkconverter.h" -#include "sbkconverter_p.h" -#include "sbkarrayconverter_p.h" -#include "basewrapper_p.h" -#include "bindingmanager.h" -#include "autodecref.h" -#include "sbkdbg.h" -#include "helper.h" -#include "voidptr.h" - -#include <unordered_map> - -static SbkConverter **PrimitiveTypeConverters; - -using ConvertersMap = std::unordered_map<std::string, SbkConverter *>; -static ConvertersMap converters; - -namespace Shiboken { -namespace Conversions { - -void initArrayConverters(); - -void init() -{ - static SbkConverter *primitiveTypeConverters[] = { - Primitive<PY_LONG_LONG>::createConverter(), - Primitive<bool>::createConverter(), - Primitive<char>::createConverter(), - Primitive<const char *>::createConverter(), - Primitive<double>::createConverter(), - Primitive<float>::createConverter(), - Primitive<int>::createConverter(), - Primitive<long>::createConverter(), - Primitive<short>::createConverter(), - Primitive<signed char>::createConverter(), - Primitive<std::string>::createConverter(), - Primitive<unsigned PY_LONG_LONG>::createConverter(), - Primitive<unsigned char>::createConverter(), - Primitive<unsigned int>::createConverter(), - Primitive<unsigned long>::createConverter(), - Primitive<unsigned short>::createConverter(), - VoidPtr::createConverter(), - Primitive<std::nullptr_t>::createConverter() - }; - PrimitiveTypeConverters = primitiveTypeConverters; - - assert(converters.empty()); - converters["PY_LONG_LONG"] = primitiveTypeConverters[SBK_PY_LONG_LONG_IDX]; - converters["bool"] = primitiveTypeConverters[SBK_BOOL_IDX_1]; - converters["char"] = primitiveTypeConverters[SBK_CHAR_IDX]; - converters["const char *"] = primitiveTypeConverters[SBK_CONSTCHARPTR_IDX]; - converters["double"] = primitiveTypeConverters[SBK_DOUBLE_IDX]; - converters["float"] = primitiveTypeConverters[SBK_FLOAT_IDX]; - converters["int"] = primitiveTypeConverters[SBK_INT_IDX]; - converters["long"] = primitiveTypeConverters[SBK_LONG_IDX]; - converters["short"] = primitiveTypeConverters[SBK_SHORT_IDX]; - converters["signed char"] = primitiveTypeConverters[SBK_SIGNEDCHAR_IDX]; - converters["std::string"] = primitiveTypeConverters[SBK_STD_STRING_IDX]; - converters["unsigned PY_LONG_LONG"] = primitiveTypeConverters[SBK_UNSIGNEDPY_LONG_LONG_IDX]; - converters["unsigned char"] = primitiveTypeConverters[SBK_UNSIGNEDCHAR_IDX]; - converters["unsigned int"] = primitiveTypeConverters[SBK_UNSIGNEDINT_IDX]; - converters["unsigned long"] = primitiveTypeConverters[SBK_UNSIGNEDLONG_IDX]; - converters["unsigned short"] = primitiveTypeConverters[SBK_UNSIGNEDSHORT_IDX]; - converters["void*"] = primitiveTypeConverters[SBK_VOIDPTR_IDX]; - converters["std::nullptr_t"] = primitiveTypeConverters[SBK_NULLPTR_T_IDX]; - - initArrayConverters(); -} - -SbkConverter *createConverterObject(PyTypeObject *type, - PythonToCppFunc toCppPointerConvFunc, - IsConvertibleToCppFunc toCppPointerCheckFunc, - CppToPythonFunc pointerToPythonFunc, - CppToPythonFunc copyToPythonFunc) -{ - auto converter = new SbkConverter; - converter->pythonType = type; - // PYSIDE-595: All types are heaptypes now, so provide reference. - Py_XINCREF(type); - - converter->pointerToPython = pointerToPythonFunc; - converter->copyToPython = copyToPythonFunc; - - if (toCppPointerCheckFunc && toCppPointerConvFunc) - converter->toCppPointerConversion = std::make_pair(toCppPointerCheckFunc, toCppPointerConvFunc); - converter->toCppConversions.clear(); - - return converter; -} - -SbkConverter *createConverter(SbkObjectType *type, - PythonToCppFunc toCppPointerConvFunc, - IsConvertibleToCppFunc toCppPointerCheckFunc, - CppToPythonFunc pointerToPythonFunc, - CppToPythonFunc copyToPythonFunc) -{ - SbkConverter *converter = - createConverterObject(reinterpret_cast<PyTypeObject *>(type), - toCppPointerConvFunc, toCppPointerCheckFunc, - pointerToPythonFunc, copyToPythonFunc); - PepType_SOTP(type)->converter = converter; - return converter; -} - -SbkConverter *createConverter(PyTypeObject *type, CppToPythonFunc toPythonFunc) -{ - return createConverterObject(type, nullptr, nullptr, nullptr, toPythonFunc); -} - -void deleteConverter(SbkConverter *converter) -{ - if (converter) { - converter->toCppConversions.clear(); - delete converter; - } -} - -void setCppPointerToPythonFunction(SbkConverter *converter, CppToPythonFunc pointerToPythonFunc) -{ - converter->pointerToPython = pointerToPythonFunc; -} - -void setPythonToCppPointerFunctions(SbkConverter *converter, - PythonToCppFunc toCppPointerConvFunc, - IsConvertibleToCppFunc toCppPointerCheckFunc) -{ - converter->toCppPointerConversion = std::make_pair(toCppPointerCheckFunc, toCppPointerConvFunc); -} - -void addPythonToCppValueConversion(SbkConverter *converter, - PythonToCppFunc pythonToCppFunc, - IsConvertibleToCppFunc isConvertibleToCppFunc) -{ - converter->toCppConversions.push_back(std::make_pair(isConvertibleToCppFunc, pythonToCppFunc)); -} -void addPythonToCppValueConversion(SbkObjectType *type, - PythonToCppFunc pythonToCppFunc, - IsConvertibleToCppFunc isConvertibleToCppFunc) -{ - addPythonToCppValueConversion(PepType_SOTP(type)->converter, pythonToCppFunc, isConvertibleToCppFunc); -} - -PyObject *pointerToPython(SbkObjectType *type, const void *cppIn) -{ - return pointerToPython(PepType_SOTP(type)->converter, cppIn); -} - -PyObject *pointerToPython(const SbkConverter *converter, const void *cppIn) -{ - assert(converter); - if (!cppIn) - Py_RETURN_NONE; - if (!converter->pointerToPython) { - warning(PyExc_RuntimeWarning, 0, "pointerToPython(): SbkConverter::pointerToPython is null for \"%s\".", - converter->pythonType->tp_name); - Py_RETURN_NONE; - } - return converter->pointerToPython(cppIn); -} - -PyObject *referenceToPython(SbkObjectType *type, const void *cppIn) -{ - return referenceToPython(PepType_SOTP(type)->converter, cppIn); -} - -PyObject *referenceToPython(const SbkConverter *converter, const void *cppIn) -{ - assert(cppIn); - - auto *pyOut = reinterpret_cast<PyObject *>(BindingManager::instance().retrieveWrapper(cppIn)); - if (pyOut) { - Py_INCREF(pyOut); - return pyOut; - } - if (!converter->pointerToPython) { - warning(PyExc_RuntimeWarning, 0, "referenceToPython(): SbkConverter::pointerToPython is null for \"%s\".", - converter->pythonType->tp_name); - Py_RETURN_NONE; - } - return converter->pointerToPython(cppIn); -} - -static inline PyObject *CopyCppToPython(const SbkConverter *converter, const void *cppIn) -{ - if (!cppIn) - Py_RETURN_NONE; - if (!converter->copyToPython) { - warning(PyExc_RuntimeWarning, 0, "CopyCppToPython(): SbkConverter::copyToPython is null for \"%s\".", - converter->pythonType->tp_name); - Py_RETURN_NONE; - } - return converter->copyToPython(cppIn); -} -PyObject *copyToPython(SbkObjectType *type, const void *cppIn) -{ - return CopyCppToPython(PepType_SOTP(type)->converter, cppIn); -} -PyObject *copyToPython(const SbkConverter *converter, const void *cppIn) -{ - return CopyCppToPython(converter, cppIn); -} - -PythonToCppFunc isPythonToCppPointerConvertible(SbkObjectType *type, PyObject *pyIn) -{ - assert(pyIn); - return PepType_SOTP(type)->converter->toCppPointerConversion.first(pyIn); -} - -static inline PythonToCppFunc IsPythonToCppConvertible(const SbkConverter *converter, PyObject *pyIn) -{ - assert(pyIn); - for (const ToCppConversion &c : converter->toCppConversions) { - if (PythonToCppFunc toCppFunc = c.first(pyIn)) - return toCppFunc; - } - return nullptr; -} -PythonToCppFunc isPythonToCppValueConvertible(SbkObjectType *type, PyObject *pyIn) -{ - return IsPythonToCppConvertible(PepType_SOTP(type)->converter, pyIn); -} -PythonToCppFunc isPythonToCppConvertible(const SbkConverter *converter, PyObject *pyIn) -{ - return IsPythonToCppConvertible(converter, pyIn); -} - -PythonToCppFunc isPythonToCppConvertible(const SbkArrayConverter *converter, - int dim1, int dim2, PyObject *pyIn) -{ - assert(pyIn); - for (IsArrayConvertibleToCppFunc f : converter->toCppConversions) { - if (PythonToCppFunc c = f(pyIn, dim1, dim2)) - return c; - } - return nullptr; -} - -PythonToCppFunc isPythonToCppReferenceConvertible(SbkObjectType *type, PyObject *pyIn) -{ - if (pyIn != Py_None) { - PythonToCppFunc toCpp = isPythonToCppPointerConvertible(type, pyIn); - if (toCpp) - return toCpp; - } - return isPythonToCppValueConvertible(type, pyIn); -} - -void nonePythonToCppNullPtr(PyObject *, void *cppOut) -{ - assert(cppOut); - *static_cast<void **>(cppOut) = nullptr; -} - -void *cppPointer(PyTypeObject *desiredType, SbkObject *pyIn) -{ - assert(pyIn); - if (!ObjectType::checkType(desiredType)) - return pyIn; - auto *inType = reinterpret_cast<SbkObjectType *>(Py_TYPE(pyIn)); - if (ObjectType::hasCast(inType)) - return ObjectType::cast(inType, pyIn, desiredType); - return Object::cppPointer(pyIn, desiredType); -} - -void pythonToCppPointer(SbkObjectType *type, PyObject *pyIn, void *cppOut) -{ - assert(type); - assert(pyIn); - assert(cppOut); - *reinterpret_cast<void **>(cppOut) = pyIn == Py_None - ? nullptr - : cppPointer(reinterpret_cast<PyTypeObject *>(type), reinterpret_cast<SbkObject *>(pyIn)); -} - -void pythonToCppPointer(const SbkConverter *converter, PyObject *pyIn, void *cppOut) -{ - assert(converter); - assert(pyIn); - assert(cppOut); - *reinterpret_cast<void **>(cppOut) = pyIn == Py_None - ? nullptr - : cppPointer(reinterpret_cast<PyTypeObject *>(converter->pythonType), reinterpret_cast<SbkObject *>(pyIn)); -} - -static void _pythonToCppCopy(const SbkConverter *converter, PyObject *pyIn, void *cppOut) -{ - assert(converter); - assert(pyIn); - assert(cppOut); - PythonToCppFunc toCpp = IsPythonToCppConvertible(converter, pyIn); - if (toCpp) - toCpp(pyIn, cppOut); -} - -void pythonToCppCopy(SbkObjectType *type, PyObject *pyIn, void *cppOut) -{ - assert(type); - _pythonToCppCopy(PepType_SOTP(type)->converter, pyIn, cppOut); -} - -void pythonToCppCopy(const SbkConverter *converter, PyObject *pyIn, void *cppOut) -{ - _pythonToCppCopy(converter, pyIn, cppOut); -} - -bool isImplicitConversion(SbkObjectType *type, PythonToCppFunc toCppFunc) -{ - // This is the Object Type or Value Type conversion that only - // retrieves the C++ pointer held in the Python wrapper. - if (toCppFunc == PepType_SOTP(type)->converter->toCppPointerConversion.second) - return false; - - // Object Types doesn't have any kind of value conversion, - // only C++ pointer retrieval. - if (PepType_SOTP(type)->converter->toCppConversions.empty()) - return false; - - // The first conversion of the non-pointer conversion list is - // a Value Type's copy to C++ function, which is not an implicit - // conversion. - // Otherwise it must be one of the implicit conversions. - // Note that we don't check if the Python to C++ conversion is in - // the list of the type's conversions, for it is expected that the - // caller knows what he's doing. - const auto conv = PepType_SOTP(type)->converter->toCppConversions.cbegin(); - return toCppFunc != (*conv).second; -} - -void registerConverterName(SbkConverter *converter , const char *typeName) -{ - auto iter = converters.find(typeName); - if (iter == converters.end()) - converters.insert(std::make_pair(typeName, converter)); -} - -SbkConverter *getConverter(const char *typeName) -{ - ConvertersMap::const_iterator it = converters.find(typeName); - if (it != converters.end()) - return it->second; - if (Py_VerboseFlag > 0) - SbkDbg() << "Can't find type resolver for type '" << typeName << "'."; - return nullptr; -} - -SbkConverter *primitiveTypeConverter(int index) -{ - return PrimitiveTypeConverters[index]; -} - -bool checkSequenceTypes(PyTypeObject *type, PyObject *pyIn) -{ - assert(type); - assert(pyIn); - if (PySequence_Size(pyIn) < 0) { - // clear the error if < 0 which means no length at all - PyErr_Clear(); - return false; - } - const Py_ssize_t size = PySequence_Size(pyIn); - for (Py_ssize_t i = 0; i < size; ++i) { - if (!PyObject_TypeCheck(AutoDecRef(PySequence_GetItem(pyIn, i)), type)) - return false; - } - return true; -} -bool convertibleSequenceTypes(const SbkConverter *converter, PyObject *pyIn) -{ - assert(converter); - assert(pyIn); - if (!PySequence_Check(pyIn)) - return false; - const Py_ssize_t size = PySequence_Size(pyIn); - for (Py_ssize_t i = 0; i < size; ++i) { - if (!isPythonToCppConvertible(converter, AutoDecRef(PySequence_GetItem(pyIn, i)))) - return false; - } - return true; -} -bool convertibleSequenceTypes(SbkObjectType *type, PyObject *pyIn) -{ - assert(type); - return convertibleSequenceTypes(PepType_SOTP(type)->converter, pyIn); -} - -bool checkPairTypes(PyTypeObject *firstType, PyTypeObject *secondType, PyObject *pyIn) -{ - assert(firstType); - assert(secondType); - assert(pyIn); - if (!PySequence_Check(pyIn)) - return false; - if (PySequence_Size(pyIn) != 2) - return false; - if (!PyObject_TypeCheck(AutoDecRef(PySequence_GetItem(pyIn, 0)), firstType)) - return false; - if (!PyObject_TypeCheck(AutoDecRef(PySequence_GetItem(pyIn, 1)), secondType)) - return false; - return true; -} -bool convertiblePairTypes(const SbkConverter *firstConverter, bool firstCheckExact, - const SbkConverter *secondConverter, bool secondCheckExact, - PyObject *pyIn) -{ - assert(firstConverter); - assert(secondConverter); - assert(pyIn); - if (!PySequence_Check(pyIn)) - return false; - if (PySequence_Size(pyIn) != 2) - return false; - AutoDecRef firstItem(PySequence_GetItem(pyIn, 0)); - if (firstCheckExact) { - if (!PyObject_TypeCheck(firstItem, firstConverter->pythonType)) - return false; - } else if (!isPythonToCppConvertible(firstConverter, firstItem)) { - return false; - } - AutoDecRef secondItem(PySequence_GetItem(pyIn, 1)); - if (secondCheckExact) { - if (!PyObject_TypeCheck(secondItem, secondConverter->pythonType)) - return false; - } else if (!isPythonToCppConvertible(secondConverter, secondItem)) { - return false; - } - - return true; -} - -bool checkDictTypes(PyTypeObject *keyType, PyTypeObject *valueType, PyObject *pyIn) -{ - assert(keyType); - assert(valueType); - assert(pyIn); - if (!PyDict_Check(pyIn)) - return false; - - PyObject *key; - PyObject *value; - Py_ssize_t pos = 0; - while (PyDict_Next(pyIn, &pos, &key, &value)) { - if (!PyObject_TypeCheck(key, keyType)) - return false; - if (!PyObject_TypeCheck(value, valueType)) - return false; - } - return true; -} - -bool convertibleDictTypes(const SbkConverter *keyConverter, bool keyCheckExact, const SbkConverter *valueConverter, - bool valueCheckExact, PyObject *pyIn) -{ - assert(keyConverter); - assert(valueConverter); - assert(pyIn); - if (!PyDict_Check(pyIn)) - return false; - PyObject *key; - PyObject *value; - Py_ssize_t pos = 0; - while (PyDict_Next(pyIn, &pos, &key, &value)) { - if (keyCheckExact) { - if (!PyObject_TypeCheck(key, keyConverter->pythonType)) - return false; - } else if (!isPythonToCppConvertible(keyConverter, key)) { - return false; - } - if (valueCheckExact) { - if (!PyObject_TypeCheck(value, valueConverter->pythonType)) - return false; - } else if (!isPythonToCppConvertible(valueConverter, value)) { - return false; - } - } - return true; -} - -PyTypeObject *getPythonTypeObject(const SbkConverter *converter) -{ - if (converter) - return converter->pythonType; - return nullptr; -} - -PyTypeObject *getPythonTypeObject(const char *typeName) -{ - return getPythonTypeObject(getConverter(typeName)); -} - -bool pythonTypeIsValueType(const SbkConverter *converter) -{ - // Unlikely to happen but for multi-inheritance SbkObjs - // the converter is not defined, hence we need a default return. - if (!converter) - return false; - return converter->pointerToPython && converter->copyToPython; -} - -bool pythonTypeIsObjectType(const SbkConverter *converter) -{ - return converter->pointerToPython && !converter->copyToPython; -} - -bool pythonTypeIsWrapperType(const SbkConverter *converter) -{ - return converter->pointerToPython != nullptr; -} - -SpecificConverter::SpecificConverter(const char *typeName) - : m_type(InvalidConversion) -{ - m_converter = getConverter(typeName); - if (!m_converter) - return; - const Py_ssize_t len = strlen(typeName); - char lastChar = typeName[len -1]; - if (lastChar == '&') { - m_type = ReferenceConversion; - } else if (lastChar == '*' || pythonTypeIsObjectType(m_converter)) { - m_type = PointerConversion; - } else { - m_type = CopyConversion; - } -} - -PyObject *SpecificConverter::toPython(const void *cppIn) -{ - switch (m_type) { - case CopyConversion: - return copyToPython(m_converter, cppIn); - case PointerConversion: - return pointerToPython(m_converter, *static_cast<const void * const *>(cppIn)); - case ReferenceConversion: - return referenceToPython(m_converter, cppIn); - default: - PyErr_SetString(PyExc_RuntimeError, "tried to use invalid converter in 'C++ to Python' conversion"); - } - return nullptr; -} - -void SpecificConverter::toCpp(PyObject *pyIn, void *cppOut) -{ - switch (m_type) { - case CopyConversion: - pythonToCppCopy(m_converter, pyIn, cppOut); - break; - case PointerConversion: - pythonToCppPointer(m_converter, pyIn, cppOut); - break; - case ReferenceConversion: - pythonToCppPointer(m_converter, pyIn, &cppOut); - break; - default: - PyErr_SetString(PyExc_RuntimeError, "tried to use invalid converter in 'Python to C++' conversion"); - } -} - -} } // namespace Shiboken::Conversions diff --git a/sources/shiboken2/libshiboken/sbkconverter.h b/sources/shiboken2/libshiboken/sbkconverter.h deleted file mode 100644 index 6c7a29300..000000000 --- a/sources/shiboken2/libshiboken/sbkconverter.h +++ /dev/null @@ -1,405 +0,0 @@ -/**************************************************************************** -** -** Copyright (C) 2016 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$ -** -****************************************************************************/ - -#ifndef SBK_CONVERTER_H -#define SBK_CONVERTER_H - -#include "sbkpython.h" -#include "shibokenmacros.h" - -#include <limits> -#include <string> - -struct SbkObject; -struct SbkObjectType; - -/** - * This is a convenience macro identical to Python's PyObject_TypeCheck, - * except that the arguments have swapped places, for the great convenience - * of generator. - */ -#define SbkObject_TypeCheck(tp, ob) \ - (Py_TYPE(ob) == (tp) || PyType_IsSubtype(Py_TYPE(ob), (tp))) - -extern "C" -{ - -/** - * SbkConverter is used to perform type conversions from C++ - * to Python and vice-versa;.and it is also used for type checking. - * SbkConverter is a private structure that must be accessed - * using the functions provided by the converter API. - */ -struct SbkConverter; -struct SbkArrayConverter; - -/** - * Given a void pointer to a C++ object, this function must return - * the proper Python object. It may be either an existing wrapper - * for the C++ object, or a newly create one. Or even the Python - * equivalent of the C++ value passed in the argument. - * - * C++ -> Python - */ -typedef PyObject *(*CppToPythonFunc)(const void *); - -/** - * This function converts a Python object to a C++ value, it may be - * a pointer, value, class, container or primitive type, passed via - * a void pointer, that will be cast properly inside the function. - * This function is usually returned by an IsConvertibleToCppFunc - * function, or obtained knowing the type of the Python object input, - * thus it will not check the Python object type, and will expect - * the void pointer to be pointing to a proper variable. - * - * Python -> C++ - */ -typedef void (*PythonToCppFunc)(PyObject *,void *); - -/** - * Checks if the Python object passed in the argument is convertible to a - * C++ type defined inside the function, it returns the converter function - * that will transform a Python argument into a C++ value. - * It returns NULL if the Python object is not convertible to the C++ type - * that the function represents. - * - * Python -> C++ ? - */ -typedef PythonToCppFunc (*IsConvertibleToCppFunc)(PyObject *); - -} // extern "C" - -namespace Shiboken { -namespace Conversions { - - -class LIBSHIBOKEN_API SpecificConverter -{ -public: - enum Type - { - InvalidConversion, - CopyConversion, - PointerConversion, - ReferenceConversion - }; - - explicit SpecificConverter(const char *typeName); - - inline SbkConverter *converter() { return m_converter; } - inline operator SbkConverter *() const { return m_converter; } - - inline bool isValid() { return m_type != InvalidConversion; } - inline operator bool() const { return m_type != InvalidConversion; } - - inline Type conversionType() { return m_type; } - - PyObject *toPython(const void *cppIn); - void toCpp(PyObject *pyIn, void *cppOut); -private: - SbkConverter *m_converter; - Type m_type; -}; - - -/** - * Creates a converter for a wrapper type. - * \param type A Shiboken.ObjectType that will receive the new converter. - * \param toCppPointerConvFunc Function to retrieve the C++ pointer held by a Python wrapper. - * \param toCppPointerCheckFunc Check and return the retriever function of the C++ pointer held by a Python wrapper. - * \param pointerToPythonFunc Function to convert a C++ object to a Python \p type wrapper, keeping their identity. - * \param copyToPythonFunc Function to convert a C++ object to a Python \p type, copying the object. - * \returns The new converter referred by the wrapper \p type. - */ -LIBSHIBOKEN_API SbkConverter *createConverter(SbkObjectType *type, - PythonToCppFunc toCppPointerConvFunc, - IsConvertibleToCppFunc toCppPointerCheckFunc, - CppToPythonFunc pointerToPythonFunc, - CppToPythonFunc copyToPythonFunc = nullptr); - -/** - * Creates a converter for a non wrapper type (primitive or container type). - * \param type Python type representing to the new converter. - * \param toPythonFunc Function to convert a C++ object to a Python \p type. - * \returns A new type converter. - */ -LIBSHIBOKEN_API SbkConverter *createConverter(PyTypeObject *type, CppToPythonFunc toPythonFunc); - -LIBSHIBOKEN_API void deleteConverter(SbkConverter *converter); - -/// Sets the Python object to C++ pointer conversion function. -LIBSHIBOKEN_API void setCppPointerToPythonFunction(SbkConverter *converter, CppToPythonFunc pointerToPythonFunc); - -/// Sets the C++ pointer to Python object conversion functions. -LIBSHIBOKEN_API void setPythonToCppPointerFunctions(SbkConverter *converter, - PythonToCppFunc toCppPointerConvFunc, - IsConvertibleToCppFunc toCppPointerCheckFunc); - -/** - * Adds a new conversion of a Python object to a C++ value. - * This is used in copy and implicit conversions. - */ -LIBSHIBOKEN_API void addPythonToCppValueConversion(SbkConverter *converter, - PythonToCppFunc pythonToCppFunc, - IsConvertibleToCppFunc isConvertibleToCppFunc); -LIBSHIBOKEN_API void addPythonToCppValueConversion(SbkObjectType *type, - PythonToCppFunc pythonToCppFunc, - IsConvertibleToCppFunc isConvertibleToCppFunc); - -// C++ -> Python --------------------------------------------------------------------------- - -/** - * Retrieves the Python wrapper object for the given \p cppIn C++ pointer object. - * This function is used only for Value and Object Types. - * Example usage: - * TYPE *var; - * PyObject *pyVar = pointerToPython(SBKTYPE, &var); - */ -LIBSHIBOKEN_API PyObject *pointerToPython(SbkObjectType *type, const void *cppIn); -LIBSHIBOKEN_API PyObject *pointerToPython(const SbkConverter *converter, const void *cppIn); - -/** - * For the given \p cppIn C++ reference it returns the Python wrapper object, - * always for Object Types, and when they already exist for reference types; - * for when the latter doesn't have an existing wrapper type, the C++ object - * is copied to Python. - * Example usage: - * TYPE &var = SOMETHING; - * PyObject *pyVar = referenceToPython(SBKTYPE, &var); - */ -LIBSHIBOKEN_API PyObject *referenceToPython(SbkObjectType *type, const void *cppIn); -LIBSHIBOKEN_API PyObject *referenceToPython(const SbkConverter *converter, const void *cppIn); - -/** - * Retrieves the Python wrapper object for the given C++ value pointed by \p cppIn. - * This function is used only for Value Types. - * Example usage: - * TYPE var; - * PyObject *pyVar = copyToPython(SBKTYPE, &var); - */ -LIBSHIBOKEN_API PyObject *copyToPython(SbkObjectType *type, const void *cppIn); -LIBSHIBOKEN_API PyObject *copyToPython(const SbkConverter *converter, const void *cppIn); - -// Python -> C++ --------------------------------------------------------------------------- - -/** - * Returns a Python to C++ conversion function if the Python object is convertible to a C++ pointer. - * It returns NULL if the Python object is not convertible to \p type. - */ -LIBSHIBOKEN_API PythonToCppFunc isPythonToCppPointerConvertible(SbkObjectType *type, PyObject *pyIn); - -/** - * Returns a Python to C++ conversion function if the Python object is convertible to a C++ value. - * The resulting converter function will create a copy of the Python object in C++, or implicitly - * convert the object to the expected \p type. - * It returns NULL if the Python object is not convertible to \p type. - */ -LIBSHIBOKEN_API PythonToCppFunc isPythonToCppValueConvertible(SbkObjectType *type, PyObject *pyIn); - -/** - * Returns a Python to C++ conversion function if the Python object is convertible to a C++ reference. - * The resulting converter function will return the underlying C++ object held by the Python wrapper, - * or a new C++ value if it must be a implicit conversion. - * It returns NULL if the Python object is not convertible to \p type. - */ -LIBSHIBOKEN_API PythonToCppFunc isPythonToCppReferenceConvertible(SbkObjectType *type, PyObject *pyIn); - -/// This is the same as isPythonToCppValueConvertible function. -LIBSHIBOKEN_API PythonToCppFunc isPythonToCppConvertible(const SbkConverter *converter, PyObject *pyIn); -LIBSHIBOKEN_API PythonToCppFunc isPythonToCppConvertible(const SbkArrayConverter *converter, - int dim1, int dim2, PyObject *pyIn); - -/** - * Returns the C++ pointer for the \p pyIn object cast to the type passed via \p desiredType. - * It differs from Shiboken::Object::cppPointer because it casts the pointer to a proper - * memory offset depending on the desired type. - */ -LIBSHIBOKEN_API void *cppPointer(PyTypeObject *desiredType, SbkObject *pyIn); - -/// Converts a Python object \p pyIn to C++ and stores the result in the C++ pointer passed in \p cppOut. -LIBSHIBOKEN_API void pythonToCppPointer(SbkObjectType *type, PyObject *pyIn, void *cppOut); -LIBSHIBOKEN_API void pythonToCppPointer(const SbkConverter *converter, PyObject *pyIn, void *cppOut); - -/// Converts a Python object \p pyIn to C++, and copies the result in the C++ variable passed in \p cppOut. -LIBSHIBOKEN_API void pythonToCppCopy(SbkObjectType *type, PyObject *pyIn, void *cppOut); -LIBSHIBOKEN_API void pythonToCppCopy(const SbkConverter *converter, PyObject *pyIn, void *cppOut); - -/** - * Helper function returned by generated convertible checking functions - * that returns a C++ NULL when the input Python object is None. - */ -LIBSHIBOKEN_API void nonePythonToCppNullPtr(PyObject *, void *cppOut); - -/** - * Returns true if the \p toCpp function passed is an implicit conversion of Python \p type. - * It is used when C++ expects a reference argument, so it may be the same object received - * from Python, or another created through implicit conversion. - */ -LIBSHIBOKEN_API bool isImplicitConversion(SbkObjectType *type, PythonToCppFunc toCpp); - -/// Registers a converter with a type name that may be used to retrieve the converter. -LIBSHIBOKEN_API void registerConverterName(SbkConverter *converter, const char *typeName); - -/// Returns the converter for a given type name, or NULL if it wasn't registered before. -LIBSHIBOKEN_API SbkConverter *getConverter(const char *typeName); - -/// Returns the converter for a primitive type. -LIBSHIBOKEN_API SbkConverter *primitiveTypeConverter(int index); - -/// Returns true if a Python sequence is comprised of objects of the given \p type. -LIBSHIBOKEN_API bool checkSequenceTypes(PyTypeObject *type, PyObject *pyIn); - -/// Returns true if a Python sequence is comprised of objects of a type convertible to the one represented by the given \p converter. -LIBSHIBOKEN_API bool convertibleSequenceTypes(const SbkConverter *converter, PyObject *pyIn); - -/// Returns true if a Python sequence is comprised of objects of a type convertible to \p type. -LIBSHIBOKEN_API bool convertibleSequenceTypes(SbkObjectType *type, PyObject *pyIn); - -/// Returns true if a Python sequence can be converted to a C++ pair. -LIBSHIBOKEN_API bool checkPairTypes(PyTypeObject *firstType, PyTypeObject *secondType, PyObject *pyIn); - -/// Returns true if a Python sequence can be converted to a C++ pair. -LIBSHIBOKEN_API bool convertiblePairTypes(const SbkConverter *firstConverter, bool firstCheckExact, - const SbkConverter *secondConverter, bool secondCheckExact, - PyObject *pyIn); - -/// Returns true if a Python dictionary can be converted to a C++ hash or map. -LIBSHIBOKEN_API bool checkDictTypes(PyTypeObject *keyType, PyTypeObject *valueType, PyObject *pyIn); - -/// Returns true if a Python dictionary can be converted to a C++ hash or map. -LIBSHIBOKEN_API bool convertibleDictTypes(const SbkConverter *keyConverter, bool keyCheckExact, - const SbkConverter *valueConverter, bool valueCheckExact, - PyObject *pyIn); - -/// Returns the Python type object associated with the given \p converter. -LIBSHIBOKEN_API PyTypeObject *getPythonTypeObject(const SbkConverter *converter); - -/// Returns the Python type object for the given \p typeName. -LIBSHIBOKEN_API PyTypeObject *getPythonTypeObject(const char *typeName); - -/// Returns true if the Python type associated with the converter is a value type. -LIBSHIBOKEN_API bool pythonTypeIsValueType(const SbkConverter *converter); - -/// Returns true if the Python type associated with the converter is an object type. -LIBSHIBOKEN_API bool pythonTypeIsObjectType(const SbkConverter *converter); - -/// Returns true if the Python type associated with the converter is a wrapper type. -LIBSHIBOKEN_API bool pythonTypeIsWrapperType(const SbkConverter *converter); - -#define SBK_PY_LONG_LONG_IDX 0 -// Qt5: name collision in QtCore after QBool is replaced by bool -#define SBK_BOOL_IDX_1 1 -#define SBK_CHAR_IDX 2 -#define SBK_CONSTCHARPTR_IDX 3 -#define SBK_DOUBLE_IDX 4 -#define SBK_FLOAT_IDX 5 -#define SBK_INT_IDX 6 -#define SBK_SIGNEDINT_IDX 6 -#define SBK_LONG_IDX 7 -#define SBK_SHORT_IDX 8 -#define SBK_SIGNEDCHAR_IDX 9 -#define SBK_STD_STRING_IDX 10 -#define SBK_UNSIGNEDPY_LONG_LONG_IDX 11 -#define SBK_UNSIGNEDCHAR_IDX 12 -#define SBK_UNSIGNEDINT_IDX 13 -#define SBK_UNSIGNEDLONG_IDX 14 -#define SBK_UNSIGNEDSHORT_IDX 15 -#define SBK_VOIDPTR_IDX 16 -#define SBK_NULLPTR_T_IDX 17 - -template<typename T> SbkConverter *PrimitiveTypeConverter() { return nullptr; } -template<> inline SbkConverter *PrimitiveTypeConverter<PY_LONG_LONG>() { return primitiveTypeConverter(SBK_PY_LONG_LONG_IDX); } -template<> inline SbkConverter *PrimitiveTypeConverter<bool>() { return primitiveTypeConverter(SBK_BOOL_IDX_1); } -template<> inline SbkConverter *PrimitiveTypeConverter<char>() { return primitiveTypeConverter(SBK_CHAR_IDX); } -template<> inline SbkConverter *PrimitiveTypeConverter<const char *>() { return primitiveTypeConverter(SBK_CONSTCHARPTR_IDX); } -template<> inline SbkConverter *PrimitiveTypeConverter<double>() { return primitiveTypeConverter(SBK_DOUBLE_IDX); } -template<> inline SbkConverter *PrimitiveTypeConverter<float>() { return primitiveTypeConverter(SBK_FLOAT_IDX); } -template<> inline SbkConverter *PrimitiveTypeConverter<int>() { return primitiveTypeConverter(SBK_INT_IDX); } -template<> inline SbkConverter *PrimitiveTypeConverter<long>() { return primitiveTypeConverter(SBK_LONG_IDX); } -template<> inline SbkConverter *PrimitiveTypeConverter<short>() { return primitiveTypeConverter(SBK_SHORT_IDX); } -template<> inline SbkConverter *PrimitiveTypeConverter<signed char>() { return primitiveTypeConverter(SBK_SIGNEDCHAR_IDX); } -template<> inline SbkConverter *PrimitiveTypeConverter<std::string>() { return primitiveTypeConverter(SBK_STD_STRING_IDX); } -template<> inline SbkConverter *PrimitiveTypeConverter<unsigned PY_LONG_LONG>() { return primitiveTypeConverter(SBK_UNSIGNEDPY_LONG_LONG_IDX); } -template<> inline SbkConverter *PrimitiveTypeConverter<unsigned char>() { return primitiveTypeConverter(SBK_UNSIGNEDCHAR_IDX); } -template<> inline SbkConverter *PrimitiveTypeConverter<unsigned int>() { return primitiveTypeConverter(SBK_UNSIGNEDINT_IDX); } -template<> inline SbkConverter *PrimitiveTypeConverter<unsigned long>() { return primitiveTypeConverter(SBK_UNSIGNEDLONG_IDX); } -template<> inline SbkConverter *PrimitiveTypeConverter<unsigned short>() { return primitiveTypeConverter(SBK_UNSIGNEDSHORT_IDX); } -template<> inline SbkConverter *PrimitiveTypeConverter<void *>() { return primitiveTypeConverter(SBK_VOIDPTR_IDX); } -template<> inline SbkConverter *PrimitiveTypeConverter<std::nullptr_t>() { return primitiveTypeConverter(SBK_NULLPTR_T_IDX); } - -} // namespace Shiboken::Conversions - -/** -* This function template is used to get the PyTypeObject of a C++ type T. -* All implementations should be provided by template specializations generated by the generator when -* T isn't a C++ primitive type. -* \see SpecialCastFunction -*/ -template<typename T> PyTypeObject *SbkType() { return nullptr; } - -// Below are the template specializations for C++ primitive types. -template<> inline PyTypeObject *SbkType<PY_LONG_LONG>() { return &PyLong_Type; } -template<> inline PyTypeObject *SbkType<bool>() { return &PyBool_Type; } -template<> inline PyTypeObject *SbkType<char>() { return &PyInt_Type; } -template<> inline PyTypeObject *SbkType<double>() { return &PyFloat_Type; } -template<> inline PyTypeObject *SbkType<float>() { return &PyFloat_Type; } -template<> inline PyTypeObject *SbkType<int>() { return &PyInt_Type; } -template<> inline PyTypeObject *SbkType<long>() { return &PyLong_Type; } -template<> inline PyTypeObject *SbkType<short>() { return &PyInt_Type; } -template<> inline PyTypeObject *SbkType<signed char>() { return &PyInt_Type; } -template<> inline PyTypeObject *SbkType<unsigned PY_LONG_LONG>() { return &PyLong_Type; } -template<> inline PyTypeObject *SbkType<unsigned char>() { return &PyInt_Type; } -template<> inline PyTypeObject *SbkType<unsigned int>() { return &PyLong_Type; } -template<> inline PyTypeObject *SbkType<unsigned long>() { return &PyLong_Type; } -template<> inline PyTypeObject *SbkType<unsigned short>() { return &PyInt_Type; } -template<> inline PyTypeObject *SbkType<std::nullptr_t>() { return Py_TYPE(&_Py_NoneStruct); } - -} // namespace Shiboken - -// When the user adds a function with an argument unknown for the typesystem, the generator writes type checks as -// TYPENAME_Check, so this macro allows users to add PyObject arguments to their added functions. -#define PyObject_Check(X) true -#define SbkChar_Check(X) (SbkNumber_Check(X) || Shiboken::String::checkChar(X)) - -struct _SbkGenericTypePrivate { - SbkConverter **converter; -}; - - -#endif // SBK_CONVERTER_H diff --git a/sources/shiboken2/libshiboken/sbkconverter_p.h b/sources/shiboken2/libshiboken/sbkconverter_p.h deleted file mode 100644 index 7508d98a4..000000000 --- a/sources/shiboken2/libshiboken/sbkconverter_p.h +++ /dev/null @@ -1,558 +0,0 @@ -/**************************************************************************** -** -** Copyright (C) 2016 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$ -** -****************************************************************************/ - -#ifndef SBK_CONVERTER_P_H -#define SBK_CONVERTER_P_H - -#include "sbkpython.h" -#include "sbkconverter.h" -#include "sbkstring.h" -#include <limits> -#include <typeinfo> -#include <sstream> -#include <iostream> -#include <vector> - -#include "sbkdbg.h" - -extern "C" -{ - -using ToCppConversion = std::pair<IsConvertibleToCppFunc, PythonToCppFunc>; -using ToCppConversionVector = std::vector<ToCppConversion>; - -/** - * \internal - * Private structure of SbkConverter. - */ -struct SbkConverter -{ - /** - * Python type associated with this converter. If the type is a Shiboken - * wrapper, then it must be a SbkObjectType; otherwise it will be the - * Python type to which the C++ value will be converted (note that the - * C++ type could be produced from various Python types). - */ - PyTypeObject *pythonType; - /** - * This function converts a C++ object to a Python object of the type - * indicated in pythonType. The identity of the C++ object is kept, - * because it looks for an already existing Python wrapper associated - * with the C++ instance. - * It is used to convert C++ pointers and references to Python objects. - */ - CppToPythonFunc pointerToPython; - /** - * This function converts a C++ object to a Python object of the type - * indicated in pythonType. The identity of the object is not kept, - * because a new instance of the C++ object is created. - * It is used to convert objects passed by value, or reference, if said - * reference can't be traced to an object that already has a Python - * wrapper assigned for it. - */ - CppToPythonFunc copyToPython; - /** - * This is a special case of a Python to C++ conversion. It returns - * the underlying C++ pointer of a Python wrapper passed as parameter - * or NULL if the Python object is a None value. - * It comes separated from the other toCppConversions because if you - * have a Python object representing a Value Type the type checking - * for both ValueType and ValueType *would be the same, thus the first - * check would be true and the second would never be reached. - */ - ToCppConversion toCppPointerConversion; - /** - * This is a list of type checking functions that return the - * proper Python to C++ conversion function, for the given Python - * object. - * For Object Types, that never have implicit conversions, this - * list is always empty. - */ - ToCppConversionVector toCppConversions; -}; - -} // extern "C" - -template<typename T, typename MaxLimitType, bool isSigned> -struct OverFlowCheckerBase { - static void formatOverFlowMessage(const MaxLimitType &value, - const std::string *valueAsString = nullptr) - { - std::ostringstream str; - str << "libshiboken: Overflow: Value "; - if (valueAsString != nullptr && !valueAsString->empty()) - str << *valueAsString; - else - str << value; - str << " exceeds limits of type " - << " [" << (isSigned ? "signed" : "unsigned") - << "] \"" << typeid(T).name() - << "\" (" << sizeof(T) << "bytes)."; - const std::string message = str.str(); - PyErr_WarnEx(PyExc_RuntimeWarning, message.c_str(), 0); - } - - // Checks if an overflow occurred inside Python code. - // Precondition: use after calls like PyLong_AsLongLong or PyLong_AsUnsignedLongLong. - // Postcondition: if error ocurred, sets the string reference to the string representation of - // the passed value. - static bool checkForInternalPyOverflow(PyObject *pyIn, std::string &valueAsString) - { - if (PyErr_Occurred()) { - PyErr_Print(); - PyObject *stringRepresentation = PyObject_Str(pyIn); - const char *cString = Shiboken::String::toCString(stringRepresentation); - valueAsString.assign(cString); - Py_DECREF(stringRepresentation); - return true; - } - return false; - } -}; - -// Helper template for checking if a value overflows when cast to type T. -// The MaxLimitType size is usually >= than type T size, so that it can still represent values that -// can't be stored in T (unless the types are of course the same). -// TLDR: MaxLimitType is either long long or unsigned long long. -template<typename T, typename MaxLimitType = PY_LONG_LONG, - bool isSigned = std::numeric_limits<T>::is_signed > -struct OverFlowChecker; - -template<typename T, typename MaxLimitType> -struct OverFlowChecker<T, MaxLimitType, true> : - public OverFlowCheckerBase<T, MaxLimitType, true> { - static bool check(const MaxLimitType &value, PyObject *pyIn) - { - std::string valueAsString; - const bool isOverflow = - OverFlowChecker::checkForInternalPyOverflow(pyIn, valueAsString) - || value < std::numeric_limits<T>::min() - || value > std::numeric_limits<T>::max(); - if (isOverflow) - OverFlowChecker::formatOverFlowMessage(value, &valueAsString); - return isOverflow; - } -}; - -template<typename T, typename MaxLimitType> -struct OverFlowChecker<T, MaxLimitType, false> - : public OverFlowCheckerBase<T, MaxLimitType, false> { - static bool check(const MaxLimitType &value, PyObject *pyIn) - { - std::string valueAsString; - const bool isOverflow = - OverFlowChecker::checkForInternalPyOverflow(pyIn, valueAsString) - || value < 0 - || static_cast<unsigned long long>(value) > std::numeric_limits<T>::max(); - if (isOverflow) - OverFlowChecker::formatOverFlowMessage(value, &valueAsString); - return isOverflow; - } -}; -template<> -struct OverFlowChecker<PY_LONG_LONG, PY_LONG_LONG, true> : - public OverFlowCheckerBase<PY_LONG_LONG, PY_LONG_LONG, true> { - static bool check(const PY_LONG_LONG &value, PyObject *pyIn) { - std::string valueAsString; - const bool isOverflow = checkForInternalPyOverflow(pyIn, valueAsString); - if (isOverflow) - OverFlowChecker::formatOverFlowMessage(value, &valueAsString); - return isOverflow; - - } -}; -template<> -struct OverFlowChecker<double, PY_LONG_LONG, true> { - static bool check(const double &, PyObject *) { return false; } -}; -template<> -struct OverFlowChecker<float, PY_LONG_LONG, true> : - public OverFlowCheckerBase<float, PY_LONG_LONG, true> { - static bool check(const double &value, PyObject *) - { - const bool result = value < std::numeric_limits<float>::min() - || value > std::numeric_limits<float>::max(); - if (result) - formatOverFlowMessage(value); - return result; - } -}; - -// Basic primitive type converters --------------------------------------------------------- - -template <typename T> struct Primitive {}; - -template <typename T> -struct OnePrimitive -{ - static PyObject *toPython(const void *) { return nullptr; } - static PythonToCppFunc isConvertible(PyObject *) { return nullptr; } - static void toCpp(PyObject *, void *) {} - static SbkConverter *createConverter() - { - SbkConverter *converter = Shiboken::Conversions::createConverter(Shiboken::SbkType<T>(), - Primitive<T>::toPython); - Shiboken::Conversions::addPythonToCppValueConversion(converter, - Primitive<T>::toCpp, - Primitive<T>::isConvertible); - return converter; - } -}; -template <typename T> -struct TwoPrimitive : OnePrimitive<T> -{ - static PythonToCppFunc isOtherConvertible(PyObject *) { return nullptr; } - static void otherToCpp(PyObject *, void *) {} - static SbkConverter *createConverter() - { - SbkConverter *converter = OnePrimitive<T>::createConverter(); - Shiboken::Conversions::addPythonToCppValueConversion(converter, Primitive<T>::otherToCpp, Primitive<T>::isOtherConvertible); - return converter; - } -}; - -// Integers -------------------------------------------------------------------------------- - -template <typename INT> -struct IntPrimitive : TwoPrimitive<INT> -{ - static PyObject *toPython(const void *cppIn) - { - return PyInt_FromLong(*reinterpret_cast<const INT *>(cppIn)); - } - static void toCpp(PyObject *pyIn, void *cppOut) - { - double result = PyFloat_AS_DOUBLE(pyIn); - // If cast to long directly it could overflow silently. - if (OverFlowChecker<INT>::check(result, pyIn)) - PyErr_SetObject(PyExc_OverflowError, nullptr); - *reinterpret_cast<INT * >(cppOut) = static_cast<INT>(result); - } - static PythonToCppFunc isConvertible(PyObject *pyIn) - { - if (PyFloat_Check(pyIn)) - return toCpp; - return nullptr; - } - static void otherToCpp(PyObject *pyIn, void *cppOut) - { - PY_LONG_LONG result = PyLong_AsLongLong(pyIn); - if (OverFlowChecker<INT>::check(result, pyIn)) - PyErr_SetObject(PyExc_OverflowError, nullptr); - *reinterpret_cast<INT * >(cppOut) = static_cast<INT>(result); - } - static PythonToCppFunc isOtherConvertible(PyObject *pyIn) - { - if (SbkNumber_Check(pyIn)) - return otherToCpp; - return nullptr; - } -}; -template <> struct Primitive<int> : IntPrimitive<int> {}; -template <> struct Primitive<long> : IntPrimitive<long> {}; -template <> struct Primitive<short> : IntPrimitive<short> {}; -template <> struct Primitive<unsigned short> : IntPrimitive<unsigned short> {}; - -// Unsigned Long Integers ------------------------------------------------------------------ - -template <typename LONG> -struct UnsignedLongPrimitive : IntPrimitive<LONG> -{ - static PyObject *toPython(const void *cppIn) - { - return PyLong_FromUnsignedLong(*reinterpret_cast<const LONG *>(cppIn)); - } -}; -template <> struct Primitive<unsigned int> : UnsignedLongPrimitive<unsigned int> {}; -template <> struct Primitive<unsigned long> : UnsignedLongPrimitive<unsigned long> {}; - -// Big integers ---------------------------------------------------------------------------- - -template <> -struct Primitive<PY_LONG_LONG> : OnePrimitive<PY_LONG_LONG> -{ - static PyObject *toPython(const void *cppIn) - { - return PyLong_FromLongLong(*reinterpret_cast<const PY_LONG_LONG *>(cppIn)); - } - static void toCpp(PyObject *pyIn, void *cppOut) - { - PY_LONG_LONG result = PyLong_AsLongLong(pyIn); - if (OverFlowChecker<PY_LONG_LONG>::check(result, pyIn)) - PyErr_SetObject(PyExc_OverflowError, 0); - *reinterpret_cast<PY_LONG_LONG * >(cppOut) = result; - } - static PythonToCppFunc isConvertible(PyObject *pyIn) - { - if (SbkNumber_Check(pyIn)) - return toCpp; - return nullptr; - } -}; - -template <> -struct Primitive<unsigned PY_LONG_LONG> : OnePrimitive<unsigned PY_LONG_LONG> -{ - static PyObject *toPython(const void *cppIn) - { - return PyLong_FromUnsignedLongLong(*static_cast<const unsigned PY_LONG_LONG *>(cppIn)); - } - static void toCpp(PyObject *pyIn, void *cppOut) - { - if (PyLong_Check(pyIn)) { - unsigned PY_LONG_LONG result = PyLong_AsUnsignedLongLong(pyIn); - if (OverFlowChecker<unsigned PY_LONG_LONG, unsigned PY_LONG_LONG>::check(result, pyIn)) - PyErr_SetObject(PyExc_OverflowError, nullptr); - *reinterpret_cast<unsigned PY_LONG_LONG * >(cppOut) = result; - } - else { - PyErr_SetString(PyExc_TypeError, "Invalid type for unsigned long long conversion"); - } - } - static PythonToCppFunc isConvertible(PyObject *pyIn) - { - if (SbkNumber_Check(pyIn)) - return toCpp; - return nullptr; - } -}; - -// Floating point -------------------------------------------------------------------------- - -template <typename FLOAT> -struct FloatPrimitive : TwoPrimitive<FLOAT> -{ - static PyObject *toPython(const void *cppIn) - { - return PyFloat_FromDouble(*reinterpret_cast<const FLOAT *>(cppIn)); - } - static void toCpp(PyObject *pyIn, void *cppOut) - { - *reinterpret_cast<FLOAT *>(cppOut) = FLOAT(PyLong_AsLong(pyIn)); - } - static PythonToCppFunc isConvertible(PyObject *pyIn) - { - if (PyInt_Check(pyIn) || PyLong_Check(pyIn)) - return toCpp; - return nullptr; - } - static void otherToCpp(PyObject *pyIn, void *cppOut) - { - *reinterpret_cast<FLOAT *>(cppOut) = FLOAT(PyFloat_AsDouble(pyIn)); - } - static PythonToCppFunc isOtherConvertible(PyObject *pyIn) - { - if (SbkNumber_Check(pyIn)) - return otherToCpp; - return nullptr; - } -}; -template <> struct Primitive<float> : FloatPrimitive<float> {}; -template <> struct Primitive<double> : FloatPrimitive<double> {}; - -// Boolean --------------------------------------------------------------------------------- - -template <> -struct Primitive<bool> : OnePrimitive<bool> -{ - static PyObject *toPython(const void *cppIn) - { - return PyBool_FromLong(*reinterpret_cast<const bool *>(cppIn)); - } - static PythonToCppFunc isConvertible(PyObject *pyIn) - { - if (SbkNumber_Check(pyIn)) - return toCpp; - return nullptr; - } - static void toCpp(PyObject *pyIn, void *cppOut) - { - *reinterpret_cast<bool *>(cppOut) = PyInt_AS_LONG(pyIn) != 0; - } -}; - -// Characters ------------------------------------------------------------------------------ - -template <typename CHAR> -struct CharPrimitive : IntPrimitive<CHAR> -{ - static void toCpp(PyObject *pyIn, void *cppOut) - { - *reinterpret_cast<CHAR *>(cppOut) = CHAR(Shiboken::String::toCString(pyIn)[0]); - } - static PythonToCppFunc isConvertible(PyObject *pyIn) - { - if (Shiboken::String::checkChar(pyIn)) - return toCpp; - return nullptr; - } - static void otherToCpp(PyObject *pyIn, void *cppOut) - { - PY_LONG_LONG result = PyLong_AsLongLong(pyIn); - if (OverFlowChecker<CHAR>::check(result, pyIn)) - PyErr_SetObject(PyExc_OverflowError, nullptr); - *reinterpret_cast<CHAR *>(cppOut) = CHAR(result); - } - static PythonToCppFunc isOtherConvertible(PyObject *pyIn) - { - if (SbkNumber_Check(pyIn)) - return otherToCpp; - return nullptr; - } - static SbkConverter *createConverter() - { - SbkConverter *converter = IntPrimitive<CHAR>::createConverter(); - Shiboken::Conversions::addPythonToCppValueConversion(converter, CharPrimitive<CHAR>::otherToCpp, CharPrimitive<CHAR>::isOtherConvertible); - return converter; - } - -}; -template <> struct Primitive<signed char> : CharPrimitive<signed char> {}; -template <> struct Primitive<unsigned char> : CharPrimitive<unsigned char> {}; -template <> struct Primitive<char> : CharPrimitive<char> { - using CharPrimitive<char>::toPython; - static PyObject *toPython(const void *cppIn) { - return Shiboken::String::fromCString(reinterpret_cast<const char *>(cppIn), 1); - } -}; - - - -// Strings --------------------------------------------------------------------------------- - -template <> -struct Primitive<const char *> : TwoPrimitive<const char *> -{ - static PyObject *toPython(const void *cppIn) - { - if (!cppIn) - Py_RETURN_NONE; - return Shiboken::String::fromCString(reinterpret_cast<const char *>(cppIn)); - } - static void toCpp(PyObject *, void *cppOut) - { - *((const char **)cppOut) = nullptr; - } - static PythonToCppFunc isConvertible(PyObject *pyIn) - { - if (pyIn == Py_None) - return toCpp; - return nullptr; - } - static void otherToCpp(PyObject *pyIn, void *cppOut) - { - *reinterpret_cast<const char **>(cppOut) = Shiboken::String::toCString(pyIn); - } - static PythonToCppFunc isOtherConvertible(PyObject *pyIn) - { - if (Shiboken::String::check(pyIn)) - return otherToCpp; - return nullptr; - } -}; - -template <> -struct Primitive<std::string> : TwoPrimitive<std::string> -{ - static PyObject *toPython(const void *cppIn) - { - return Shiboken::String::fromCString(reinterpret_cast<const std::string *>(cppIn)->c_str()); - } - static void toCpp(PyObject *, void *cppOut) - { - reinterpret_cast<std::string *>(cppOut)->clear(); - } - static PythonToCppFunc isConvertible(PyObject *pyIn) - { - if (pyIn == Py_None) - return toCpp; - return nullptr; - } - static void otherToCpp(PyObject *pyIn, void *cppOut) - { - reinterpret_cast<std::string *>(cppOut)->assign(Shiboken::String::toCString(pyIn)); - } - static PythonToCppFunc isOtherConvertible(PyObject *pyIn) - { - if (Shiboken::String::check(pyIn)) - return otherToCpp; - return nullptr; - } -}; - -// nullptr_t -template <> -struct Primitive<std::nullptr_t> : TwoPrimitive<std::nullptr_t> -{ - static PyObject *toPython(const void * /* cppIn */) - { - return Py_None; - } - static void toCpp(PyObject *, void *cppOut) - { - *reinterpret_cast<std::nullptr_t *>(cppOut) = nullptr; - } - static PythonToCppFunc isConvertible(PyObject *pyIn) - { - if (pyIn == Py_None) - return toCpp; - return nullptr; - } - static void otherToCpp(PyObject * /* pyIn */, void *cppOut) - { - *reinterpret_cast<std::nullptr_t *>(cppOut) = nullptr; - } - static PythonToCppFunc isOtherConvertible(PyObject *pyIn) - { - if (pyIn == nullptr) - return otherToCpp; - return nullptr; - } -}; - -namespace Shiboken { -namespace Conversions { -SbkConverter *createConverterObject(PyTypeObject *type, - PythonToCppFunc toCppPointerConvFunc, - IsConvertibleToCppFunc toCppPointerCheckFunc, - CppToPythonFunc pointerToPythonFunc, - CppToPythonFunc copyToPythonFunc); -} // namespace Conversions -} // namespace Shiboken -#endif // SBK_CONVERTER_P_H diff --git a/sources/shiboken2/libshiboken/sbkdbg.h b/sources/shiboken2/libshiboken/sbkdbg.h deleted file mode 100644 index 2a3211489..000000000 --- a/sources/shiboken2/libshiboken/sbkdbg.h +++ /dev/null @@ -1,127 +0,0 @@ -/**************************************************************************** -** -** Copyright (C) 2016 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$ -** -****************************************************************************/ - -#ifndef SBKDBG_H -#define SBKDBG_H - -#include "sbkpython.h" -#include "basewrapper.h" -#include <iostream> - -#ifndef NOCOLOR - #define COLOR_END "\033[0m" - #define COLOR_WHITE "\033[1;37m" - #define COLOR_YELLOW "\033[1;33m" - #define COLOR_GREEN "\033[0;32m" - #define COLOR_RED "\033[0;31m" -#else - #define COLOR_END "" - #define COLOR_WHITE "" - #define COLOR_YELLOW "" - #define COLOR_GREEN "" - #define COLOR_RED "" -#endif - -#ifndef NDEBUG - -class BaseLogger -{ -public: - BaseLogger(const BaseLogger &) = delete; - BaseLogger(BaseLogger &&) = delete; - BaseLogger &operator=(const BaseLogger &) = delete; - BaseLogger &operator=(BaseLogger &&) = delete; - - BaseLogger(std::ostream &output, const char *function, const char *context) - : m_stream(output), m_function(function), m_context(context) {} - ~BaseLogger() - { - m_stream << std::endl; - } - std::ostream &operator()() { return m_stream; }; - template <typename T> - std::ostream &operator<<(const T &t) - { - m_stream << '['; - if (m_context[0]) - m_stream << COLOR_GREEN << m_context << COLOR_END << "|"; - return m_stream << COLOR_WHITE << m_function << COLOR_END << "] " << t; - } -private: - std::ostream &m_stream; - const char *m_function; - const char *m_context; -}; - -inline std::ostream &operator<<(std::ostream &out, PyObject *obj) -{ - PyObject *repr = Shiboken::Object::isValid(obj, false) ? PyObject_Repr(obj) : 0; - if (repr) { - PyObject *str = PyUnicode_AsUTF8String(repr); - Py_DECREF(repr); - repr = str; - out << PyBytes_AS_STRING(repr); - Py_DECREF(repr); - } else { - out << reinterpret_cast<void *>(obj); - } - return out; -} - -class _SbkDbg : public BaseLogger -{ -public: - _SbkDbg(const char *function, const char *context = "") : BaseLogger(std::cout, function, context) {} -}; - -#ifdef __GNUG__ -#define SbkDbg(X) _SbkDbg(__PRETTY_FUNCTION__, X"") -#else -#define SbkDbg(X) _SbkDbg(__FUNCTION__, X"") -#endif - -#else - -struct SbkDbg { - template <typename T> - SbkDbg &operator<<(const T &) { return *this; } -}; - -#endif -#endif // LOGGER_H diff --git a/sources/shiboken2/libshiboken/sbkenum.cpp b/sources/shiboken2/libshiboken/sbkenum.cpp deleted file mode 100644 index e5b7bd743..000000000 --- a/sources/shiboken2/libshiboken/sbkenum.cpp +++ /dev/null @@ -1,776 +0,0 @@ -/**************************************************************************** -** -** Copyright (C) 2018 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$ -** -****************************************************************************/ - -#include "sbkenum.h" -#include "sbkstring.h" -#include "sbkstaticstrings.h" -#include "sbkstaticstrings_p.h" -#include "sbkconverter.h" -#include "basewrapper.h" -#include "sbkdbg.h" -#include "autodecref.h" -#include "sbkpython.h" - -#include <string.h> -#include <cstring> -#include <vector> - -#define SBK_ENUM(ENUM) reinterpret_cast<SbkEnumObject *>(ENUM) -#define SBK_TYPE_CHECK(o) (strcmp(Py_TYPE(Py_TYPE(o))->tp_name, "Shiboken.EnumType") == 0) -typedef PyObject *(*enum_func)(PyObject *, PyObject *); - -extern "C" -{ - -struct SbkEnumTypePrivate -{ - SbkConverter **converterPtr; - SbkConverter *converter; - const char *cppName; -}; - -struct SbkEnumType -{ - PyTypeObject type; -}; - -struct SbkEnumObject -{ - PyObject_HEAD - long ob_value; - PyObject *ob_name; -}; - -static PyObject *SbkEnumObject_repr(PyObject *self) -{ - const SbkEnumObject *enumObj = SBK_ENUM(self); - if (enumObj->ob_name) - return Shiboken::String::fromFormat("%s.%s", (Py_TYPE(self))->tp_name, PyBytes_AS_STRING(enumObj->ob_name)); - else - return Shiboken::String::fromFormat("%s(%ld)", (Py_TYPE(self))->tp_name, enumObj->ob_value); -} - -static PyObject *SbkEnumObject_name(PyObject *self, void *) -{ - auto *enum_self = SBK_ENUM(self); - - if (enum_self->ob_name == nullptr) - Py_RETURN_NONE; - - Py_INCREF(enum_self->ob_name); - return enum_self->ob_name; -} - -static PyObject *SbkEnum_tp_new(PyTypeObject *type, PyObject *args, PyObject *) -{ - long itemValue = 0; - if (!PyArg_ParseTuple(args, "|l:__new__", &itemValue)) - return nullptr; - - SbkEnumObject *self = PyObject_New(SbkEnumObject, type); - if (!self) - return nullptr; - self->ob_value = itemValue; - Shiboken::AutoDecRef item(Shiboken::Enum::getEnumItemFromValue(type, itemValue)); - self->ob_name = item.object() ? SbkEnumObject_name(item, nullptr) : nullptr; - return reinterpret_cast<PyObject *>(self); -} - -void enum_object_dealloc(PyObject *ob) -{ - auto self = reinterpret_cast<SbkEnumObject *>(ob); - Py_XDECREF(self->ob_name); - Sbk_object_dealloc(ob); -} - -static PyObject *enum_op(enum_func f, PyObject *a, PyObject *b) { - PyObject *valA = a; - PyObject *valB = b; - PyObject *result = nullptr; - bool enumA = false; - bool enumB = false; - - // We are not allowing floats - if (!PyFloat_Check(valA) && !PyFloat_Check(valB)) { - // Check if both variables are SbkEnumObject - if (SBK_TYPE_CHECK(valA)) { - valA = PyLong_FromLong(SBK_ENUM(valA)->ob_value); - enumA = true; - } - if (SBK_TYPE_CHECK(valB)) { - valB = PyLong_FromLong(SBK_ENUM(valB)->ob_value); - enumB = true; - } - } - - // Without an enum we are not supporting the operation - if (!(enumA || enumB)) { - Py_INCREF(Py_NotImplemented); - return Py_NotImplemented; - } else { - result = f(valA, valB); - } - - // Decreasing the reference of the used variables a and b. - if (enumA) - Py_DECREF(valA); - if (enumB) - Py_DECREF(valB); - - return result; -} - -/* Notes: - * On Py3k land we use long type when using integer numbers. However, on older - * versions of Python (version 2) we need to convert it to int type, - * respectively. - * - * Thus calling PyInt_FromLong() will result in calling PyLong_FromLong in - * Py3k. - */ -static PyObject *enum_int(PyObject *v) -{ - return PyInt_FromLong(SBK_ENUM(v)->ob_value); -} - -static PyObject *enum_and(PyObject *self, PyObject *b) -{ - return enum_op(PyNumber_And, self, b); -} - -static PyObject *enum_or(PyObject *self, PyObject *b) -{ -return enum_op(PyNumber_Or, self, b); -} - -static PyObject *enum_xor(PyObject *self, PyObject *b) -{ - return enum_op(PyNumber_Xor, self, b); -} - -static int enum_bool(PyObject *v) -{ - return (SBK_ENUM(v)->ob_value > 0); -} - -static PyObject *enum_add(PyObject *self, PyObject *v) -{ - return enum_op(PyNumber_Add, self, v); -} - -static PyObject *enum_subtract(PyObject *self, PyObject *v) -{ - return enum_op(PyNumber_Subtract, self, v); -} - -static PyObject *enum_multiply(PyObject *self, PyObject *v) -{ -return enum_op(PyNumber_Multiply, self, v); -} - -static PyObject *enum_richcompare(PyObject *self, PyObject *other, int op) -{ - PyObject *valA = self; - PyObject *valB = other; - PyObject *result = nullptr; - bool enumA = false; - bool enumB = false; - - // We are not allowing floats - if (!PyFloat_Check(valA) && !PyFloat_Check(valB)) { - - // Check if both variables are SbkEnumObject - if (SBK_TYPE_CHECK(valA)) { - valA = PyLong_FromLong(SBK_ENUM(valA)->ob_value); - enumA = true; - } - if (SBK_TYPE_CHECK(valB)) { - valB = PyLong_FromLong(SBK_ENUM(valB)->ob_value); - enumB =true; - } - } - - // Without an enum we are not supporting the operation - if (!(enumA || enumB)) { - Py_INCREF(Py_NotImplemented); - return Py_NotImplemented; - } - result = PyObject_RichCompare(valA, valB, op); - - // Decreasing the reference of the used variables a and b. - if (enumA) - Py_DECREF(valA); - if (enumB) - Py_DECREF(valB); - - return result; -} - -static Py_hash_t enum_hash(PyObject *pyObj) -{ - Py_hash_t val = reinterpret_cast<SbkEnumObject *>(pyObj)->ob_value; - if (val == -1) - val = -2; - return val; -} - -static PyGetSetDef SbkEnumGetSetList[] = { - {const_cast<char *>("name"), &SbkEnumObject_name, nullptr, nullptr, nullptr}, - {nullptr, nullptr, nullptr, nullptr, nullptr} // Sentinel -}; - -#if PY_VERSION_HEX < 0x03000000 - -static PyObject *SbkEnumType_repr(PyObject *type) -{ - Shiboken::AutoDecRef mod(PyObject_GetAttr(type, Shiboken::PyMagicName::module())); - if (mod.isNull()) - return nullptr; - Shiboken::AutoDecRef name(PyObject_GetAttr(type, Shiboken::PyMagicName::qualname())); - if (name.isNull()) - return nullptr; - return PyString_FromFormat("<class '%s.%s'>", - PyString_AS_STRING(mod.object()), - PyString_AS_STRING(name.object())); -} - -#endif // PY_VERSION_HEX < 0x03000000 - -static void SbkEnumTypeDealloc(PyObject *pyObj); -static PyObject *SbkEnumTypeTpNew(PyTypeObject *metatype, PyObject *args, PyObject *kwds); - -static PyType_Slot SbkEnumType_Type_slots[] = { - {Py_tp_dealloc, (void *)SbkEnumTypeDealloc}, - {Py_nb_add, (void *)enum_add}, - {Py_nb_subtract, (void *)enum_subtract}, - {Py_nb_multiply, (void *)enum_multiply}, - {Py_nb_positive, (void *)enum_int}, - {Py_nb_bool, (void *)enum_bool}, - {Py_nb_and, (void *)enum_and}, - {Py_nb_xor, (void *)enum_xor}, - {Py_nb_or, (void *)enum_or}, - {Py_nb_int, (void *)enum_int}, - {Py_nb_index, (void *)enum_int}, - {Py_tp_base, (void *)&PyType_Type}, - {Py_tp_alloc, (void *)PyType_GenericAlloc}, - {Py_tp_new, (void *)SbkEnumTypeTpNew}, - {Py_tp_free, (void *)PyObject_GC_Del}, -#if PY_VERSION_HEX < 0x03000000 - {Py_tp_repr, (void *)SbkEnumType_repr}, -#endif - {0, nullptr} -}; -static PyType_Spec SbkEnumType_Type_spec = { - "1:Shiboken.EnumType", - 0, // filled in later - sizeof(PyMemberDef), - Py_TPFLAGS_DEFAULT|Py_TPFLAGS_BASETYPE|Py_TPFLAGS_CHECKTYPES, - SbkEnumType_Type_slots, -}; - - -PyTypeObject *SbkEnumType_TypeF(void) -{ - static PyTypeObject *type = nullptr; - if (!type) { - SbkEnumType_Type_spec.basicsize = - PepHeapType_SIZE + sizeof(SbkEnumTypePrivate); - type = reinterpret_cast<PyTypeObject *>(SbkType_FromSpec(&SbkEnumType_Type_spec)); - } - return type; -} - -void SbkEnumTypeDealloc(PyObject *pyObj) -{ - auto sbkType = reinterpret_cast<SbkEnumType *>(pyObj); - - PyObject_GC_UnTrack(pyObj); -#ifndef Py_LIMITED_API - Py_TRASHCAN_SAFE_BEGIN(pyObj); -#endif - if (PepType_SETP(sbkType)->converter) { - Shiboken::Conversions::deleteConverter(PepType_SETP(sbkType)->converter); - } -#ifndef Py_LIMITED_API - Py_TRASHCAN_SAFE_END(pyObj); -#endif - if (PepRuntime_38_flag) { - // PYSIDE-939: Handling references correctly. - // This was not needed before Python 3.8 (Python issue 35810) - Py_DECREF(Py_TYPE(pyObj)); - } -} - -PyObject *SbkEnumTypeTpNew(PyTypeObject *metatype, PyObject *args, PyObject *kwds) -{ - auto type_new = reinterpret_cast<newfunc>(PyType_GetSlot(&PyType_Type, Py_tp_new)); - auto newType = reinterpret_cast<SbkEnumType *>(type_new(metatype, args, kwds)); - if (!newType) - return nullptr; - return reinterpret_cast<PyObject *>(newType); -} - -} // extern "C" - -/////////////////////////////////////////////////////////////// -// -// PYSIDE-15: Pickling Support for Qt Enum objects -// This works very well and fixes the issue. -// -extern "C" { - -static void init_enum(); // forward - -static PyObject *enum_unpickler = nullptr; - -// Pickling: reduce the Qt Enum object -static PyObject *enum___reduce__(PyObject *obj) -{ - init_enum(); - return Py_BuildValue("O(Ni)", - enum_unpickler, - Py_BuildValue("s", Py_TYPE(obj)->tp_name), - PyInt_AS_LONG(obj)); -} - -} // extern "C" - -namespace Shiboken { namespace Enum { - -// Unpickling: rebuild the Qt Enum object -PyObject *unpickleEnum(PyObject *enum_class_name, PyObject *value) -{ - Shiboken::AutoDecRef parts(PyObject_CallMethod(enum_class_name, - const_cast<char *>("split"), const_cast<char *>("s"), ".")); - if (parts.isNull()) - return nullptr; - PyObject *top_name = PyList_GetItem(parts, 0); // borrowed ref - if (top_name == nullptr) - return nullptr; - PyObject *module = PyImport_GetModule(top_name); - if (module == nullptr) { - PyErr_Format(PyExc_ImportError, "could not import module %.200s", - Shiboken::String::toCString(top_name)); - return nullptr; - } - Shiboken::AutoDecRef cur_thing(module); - int len = PyList_Size(parts); - for (int idx = 1; idx < len; ++idx) { - PyObject *name = PyList_GetItem(parts, idx); // borrowed ref - PyObject *thing = PyObject_GetAttr(cur_thing, name); - if (thing == nullptr) { - PyErr_Format(PyExc_ImportError, "could not import Qt Enum type %.200s", - Shiboken::String::toCString(enum_class_name)); - return nullptr; - } - cur_thing.reset(thing); - } - PyObject *klass = cur_thing; - return PyObject_CallFunctionObjArgs(klass, value, nullptr); -} - -} // namespace Enum -} // namespace Shiboken - -extern "C" { - -// Initialization -static bool _init_enum() -{ - static PyObject *shiboken_name = Py_BuildValue("s", "shiboken2"); - if (shiboken_name == nullptr) - return false; - Shiboken::AutoDecRef shibo(PyImport_GetModule(shiboken_name)); - if (shibo.isNull()) - return false; - Shiboken::AutoDecRef sub(PyObject_GetAttr(shibo, shiboken_name)); - PyObject *mod = sub.object(); - if (mod == nullptr) { - // We are in the build dir and already in shiboken. - PyErr_Clear(); - mod = shibo.object(); - } - enum_unpickler = PyObject_GetAttrString(mod, "_unpickle_enum"); - if (enum_unpickler == nullptr) - return false; - return true; -} - -static void init_enum() -{ - if (!(enum_unpickler || _init_enum())) - Py_FatalError("could not load enum pickling helper function"); -} - -static PyMethodDef SbkEnumObject_Methods[] = { - {const_cast<char *>("__reduce__"), reinterpret_cast<PyCFunction>(enum___reduce__), - METH_NOARGS, nullptr}, - {nullptr, nullptr, 0, nullptr} // Sentinel -}; - -} // extern "C" - -// -/////////////////////////////////////////////////////////////// - -namespace Shiboken { - -class DeclaredEnumTypes -{ -public: - DeclaredEnumTypes(const DeclaredEnumTypes &) = delete; - DeclaredEnumTypes(DeclaredEnumTypes &&) = delete; - DeclaredEnumTypes &operator=(const DeclaredEnumTypes &) = delete; - DeclaredEnumTypes &operator=(DeclaredEnumTypes &&) = delete; - - DeclaredEnumTypes(); - ~DeclaredEnumTypes(); - static DeclaredEnumTypes &instance(); - void addEnumType(PyTypeObject *type); - -private: - std::vector<PyTypeObject *> m_enumTypes; -}; - -namespace Enum { - -bool check(PyObject *pyObj) -{ - return Py_TYPE(Py_TYPE(pyObj)) == SbkEnumType_TypeF(); -} - -PyObject *getEnumItemFromValue(PyTypeObject *enumType, long itemValue) -{ - PyObject *key, *value; - Py_ssize_t pos = 0; - PyObject *values = PyDict_GetItem(enumType->tp_dict, Shiboken::PyName::values()); - - while (PyDict_Next(values, &pos, &key, &value)) { - auto *obj = reinterpret_cast<SbkEnumObject *>(value); - if (obj->ob_value == itemValue) { - Py_INCREF(value); - return value; - } - } - return nullptr; -} - -static PyTypeObject *createEnum(const char *fullName, const char *cppName, - const char */* shortName */, - PyTypeObject *flagsType) -{ - PyTypeObject *enumType = newTypeWithName(fullName, cppName, flagsType); - if (PyType_Ready(enumType) < 0) { - Py_XDECREF(enumType); - return nullptr; - } - return enumType; -} - -PyTypeObject *createGlobalEnum(PyObject *module, const char *name, const char *fullName, const char *cppName, PyTypeObject *flagsType) -{ - PyTypeObject *enumType = createEnum(fullName, cppName, name, flagsType); - if (enumType && PyModule_AddObject(module, name, reinterpret_cast<PyObject *>(enumType)) < 0) { - Py_DECREF(enumType); - return nullptr; - } - if (flagsType && PyModule_AddObject(module, PepType_GetNameStr(flagsType), - reinterpret_cast<PyObject *>(flagsType)) < 0) { - Py_DECREF(enumType); - return nullptr; - } - return enumType; -} - -PyTypeObject *createScopedEnum(SbkObjectType *scope, const char *name, const char *fullName, const char *cppName, PyTypeObject *flagsType) -{ - PyTypeObject *enumType = createEnum(fullName, cppName, name, flagsType); - if (enumType && PyDict_SetItemString(reinterpret_cast<PyTypeObject *>(scope)->tp_dict, name, - reinterpret_cast<PyObject *>(enumType)) < 0) { - Py_DECREF(enumType); - return nullptr; - } - if (flagsType && PyDict_SetItemString(reinterpret_cast<PyTypeObject *>(scope)->tp_dict, - PepType_GetNameStr(flagsType), - reinterpret_cast<PyObject *>(flagsType)) < 0) { - Py_DECREF(enumType); - return nullptr; - } - return enumType; -} - -static PyObject *createEnumItem(PyTypeObject *enumType, const char *itemName, long itemValue) -{ - PyObject *enumItem = newItem(enumType, itemValue, itemName); - if (PyDict_SetItemString(enumType->tp_dict, itemName, enumItem) < 0) { - Py_DECREF(enumItem); - return nullptr; - } - return enumItem; -} - -bool createGlobalEnumItem(PyTypeObject *enumType, PyObject *module, const char *itemName, long itemValue) -{ - PyObject *enumItem = createEnumItem(enumType, itemName, itemValue); - if (!enumItem) - return false; - int ok = PyModule_AddObject(module, itemName, enumItem); - Py_DECREF(enumItem); - return ok >= 0; -} - -bool createScopedEnumItem(PyTypeObject *enumType, PyTypeObject *scope, - const char *itemName, long itemValue) -{ - PyObject *enumItem = createEnumItem(enumType, itemName, itemValue); - if (!enumItem) - return false; - int ok = PyDict_SetItemString(reinterpret_cast<PyTypeObject *>(scope)->tp_dict, itemName, enumItem); - Py_DECREF(enumItem); - return ok >= 0; -} - -bool createScopedEnumItem(PyTypeObject *enumType, SbkObjectType *scope, const char *itemName, long itemValue) -{ - return createScopedEnumItem(enumType, reinterpret_cast<PyTypeObject *>(scope), itemName, itemValue); -} - -PyObject * -newItem(PyTypeObject *enumType, long itemValue, const char *itemName) -{ - bool newValue = true; - SbkEnumObject *enumObj; - if (!itemName) { - enumObj = reinterpret_cast<SbkEnumObject *>( - getEnumItemFromValue(enumType, itemValue)); - if (enumObj) - return reinterpret_cast<PyObject *>(enumObj); - - newValue = false; - } - - enumObj = PyObject_New(SbkEnumObject, enumType); - if (!enumObj) - return nullptr; - - enumObj->ob_name = itemName ? PyBytes_FromString(itemName) : nullptr; - enumObj->ob_value = itemValue; - - if (newValue) { - auto dict = enumType->tp_dict; // Note: 'values' is borrowed - PyObject *values = PyDict_GetItemWithError(dict, Shiboken::PyName::values()); - if (values == nullptr) { - if (PyErr_Occurred()) - return nullptr; - Shiboken::AutoDecRef new_values(values = PyDict_New()); - if (values == nullptr) - return nullptr; - if (PyDict_SetItem(dict, Shiboken::PyName::values(), values) < 0) - return nullptr; - } - PyDict_SetItemString(values, itemName, reinterpret_cast<PyObject *>(enumObj)); - } - - return reinterpret_cast<PyObject *>(enumObj); -} - -static PyType_Slot SbkNewType_slots[] = { - {Py_tp_repr, (void *)SbkEnumObject_repr}, - {Py_tp_str, (void *)SbkEnumObject_repr}, - {Py_tp_getset, (void *)SbkEnumGetSetList}, - {Py_tp_methods, (void *)SbkEnumObject_Methods}, - {Py_tp_new, (void *)SbkEnum_tp_new}, - {Py_nb_add, (void *)enum_add}, - {Py_nb_subtract, (void *)enum_subtract}, - {Py_nb_multiply, (void *)enum_multiply}, - {Py_nb_positive, (void *)enum_int}, - {Py_nb_bool, (void *)enum_bool}, - {Py_nb_and, (void *)enum_and}, - {Py_nb_xor, (void *)enum_xor}, - {Py_nb_or, (void *)enum_or}, - {Py_nb_int, (void *)enum_int}, - {Py_nb_index, (void *)enum_int}, - {Py_tp_richcompare, (void *)enum_richcompare}, - {Py_tp_hash, (void *)enum_hash}, - {Py_tp_dealloc, (void *)enum_object_dealloc}, - {0, nullptr} -}; -static PyType_Spec SbkNewType_spec = { - "missing Enum name", // to be inserted later - sizeof(SbkEnumObject), - 0, - Py_TPFLAGS_DEFAULT|Py_TPFLAGS_CHECKTYPES, - SbkNewType_slots, -}; - -static void -copyNumberMethods(PyTypeObject *flagsType, - PyType_Slot number_slots[], - int *pidx) -{ - int idx = *pidx; -#define PUT_SLOT(name) \ - number_slots[idx].slot = (name); \ - number_slots[idx].pfunc = PyType_GetSlot(flagsType, (name)); \ - ++idx; - - PUT_SLOT(Py_nb_absolute); - PUT_SLOT(Py_nb_add); - PUT_SLOT(Py_nb_and); - PUT_SLOT(Py_nb_bool); - PUT_SLOT(Py_nb_divmod); - PUT_SLOT(Py_nb_float); - PUT_SLOT(Py_nb_floor_divide); - PUT_SLOT(Py_nb_index); - PUT_SLOT(Py_nb_inplace_add); - PUT_SLOT(Py_nb_inplace_and); - PUT_SLOT(Py_nb_inplace_floor_divide); - PUT_SLOT(Py_nb_inplace_lshift); - PUT_SLOT(Py_nb_inplace_multiply); - PUT_SLOT(Py_nb_inplace_or); - PUT_SLOT(Py_nb_inplace_power); - PUT_SLOT(Py_nb_inplace_remainder); - PUT_SLOT(Py_nb_inplace_rshift); - PUT_SLOT(Py_nb_inplace_subtract); - PUT_SLOT(Py_nb_inplace_true_divide); - PUT_SLOT(Py_nb_inplace_xor); - PUT_SLOT(Py_nb_int); - PUT_SLOT(Py_nb_invert); - PUT_SLOT(Py_nb_lshift); - PUT_SLOT(Py_nb_multiply); - PUT_SLOT(Py_nb_negative); - PUT_SLOT(Py_nb_or); - PUT_SLOT(Py_nb_positive); - PUT_SLOT(Py_nb_power); - PUT_SLOT(Py_nb_remainder); - PUT_SLOT(Py_nb_rshift); - PUT_SLOT(Py_nb_subtract); - PUT_SLOT(Py_nb_true_divide); - PUT_SLOT(Py_nb_xor); -#undef PUT_SLOT - *pidx = idx; -} - -PyTypeObject * -newTypeWithName(const char *name, - const char *cppName, - PyTypeObject *numbers_fromFlag) -{ - // Careful: SbkType_FromSpec does not allocate the string. - PyType_Slot newslots[99] = {}; // enough but not too big for the stack - PyType_Spec newspec; - newspec.name = strdup(name); - newspec.basicsize = SbkNewType_spec.basicsize; - newspec.itemsize = SbkNewType_spec.itemsize; - newspec.flags = SbkNewType_spec.flags; - // we must append all the number methods, so rebuild everything: - int idx = 0; - while (SbkNewType_slots[idx].slot) { - newslots[idx].slot = SbkNewType_slots[idx].slot; - newslots[idx].pfunc = SbkNewType_slots[idx].pfunc; - ++idx; - } - if (numbers_fromFlag) - copyNumberMethods(numbers_fromFlag, newslots, &idx); - newspec.slots = newslots; - auto *type = reinterpret_cast<PyTypeObject *>(SbkType_FromSpec(&newspec)); - Py_TYPE(type) = SbkEnumType_TypeF(); - - auto *enumType = reinterpret_cast<SbkEnumType *>(type); - PepType_SETP(enumType)->cppName = cppName; - PepType_SETP(enumType)->converterPtr = &PepType_SETP(enumType)->converter; - DeclaredEnumTypes::instance().addEnumType(type); - return type; -} - -const char *getCppName(PyTypeObject *enumType) -{ - assert(Py_TYPE(enumType) == SbkEnumType_TypeF()); - return PepType_SETP(reinterpret_cast<SbkEnumType *>(enumType))->cppName; -} - -long int getValue(PyObject *enumItem) -{ - assert(Shiboken::Enum::check(enumItem)); - return reinterpret_cast<SbkEnumObject *>(enumItem)->ob_value; -} - -void setTypeConverter(PyTypeObject *enumType, SbkConverter *converter) -{ - //reinterpret_cast<SbkEnumType *>(enumType)->converter = converter; - *PepType_SGTP(enumType)->converter = converter; -} - -SbkConverter *getTypeConverter(PyTypeObject *enumType) -{ - //return reinterpret_cast<SbkEnumType *>(enumType)->converter; - return *PepType_SGTP(enumType)->converter; -} - -} // namespace Enum - -DeclaredEnumTypes &DeclaredEnumTypes::instance() -{ - static DeclaredEnumTypes me; - return me; -} - -DeclaredEnumTypes::DeclaredEnumTypes() = default; - -DeclaredEnumTypes::~DeclaredEnumTypes() -{ - /* - * PYSIDE-595: This was "delete *it;" before introducing 'SbkType_FromSpec'. - * XXX what should I do now? - * Refcounts in tests are 30 or 0 at end. - * When I add the default tp_dealloc, we get negative refcounts! - * So right now I am doing nothing. Surely wrong but no crash. - * See also the comment in function 'createGlobalEnumItem'. - */ - // for (PyTypeObject *o : m_enumTypes) - // fprintf(stderr, "ttt %d %s\n", Py_REFCNT(o), o->tp_name); - m_enumTypes.clear(); -} - -void DeclaredEnumTypes::addEnumType(PyTypeObject *type) -{ - m_enumTypes.push_back(type); -} - -} diff --git a/sources/shiboken2/libshiboken/sbkenum.h b/sources/shiboken2/libshiboken/sbkenum.h deleted file mode 100644 index c294c17d9..000000000 --- a/sources/shiboken2/libshiboken/sbkenum.h +++ /dev/null @@ -1,123 +0,0 @@ -/**************************************************************************** -** -** Copyright (C) 2016 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$ -** -****************************************************************************/ - -#ifndef SBKENUM_H -#define SBKENUM_H - -#include "sbkpython.h" -#include "shibokenmacros.h" - -extern "C" -{ - -extern LIBSHIBOKEN_API PyTypeObject *SbkEnumType_TypeF(void); -struct SbkObjectType; -struct SbkConverter; -struct SbkEnumType; -struct SbkEnumTypePrivate; - -} // extern "C" - -namespace Shiboken -{ - -inline bool isShibokenEnum(PyObject *pyObj) -{ - return Py_TYPE(Py_TYPE(pyObj)) == SbkEnumType_TypeF(); -} - -namespace Enum -{ - LIBSHIBOKEN_API bool check(PyObject *obj); - /** - * Creates a new enum type (and its flags type, if any is given) - * and registers it to Python and adds it to \p module. - * \param module Module to where the new enum type will be added. - * \param name Name of the enum. - * \param fullName Name of the enum that includes all scope information (e.g.: "module.Enum"). - * \param cppName Full qualified C++ name of the enum. - * \param flagsType Optional Python type for the flags associated with the enum. - * \return The new enum type or NULL if it fails. - */ - LIBSHIBOKEN_API PyTypeObject *createGlobalEnum(PyObject *module, - const char *name, - const char *fullName, - const char *cppName, - PyTypeObject *flagsType = nullptr); - /// This function does the same as createGlobalEnum, but adds the enum to a Shiboken type or namespace. - LIBSHIBOKEN_API PyTypeObject *createScopedEnum(SbkObjectType *scope, - const char *name, - const char *fullName, - const char *cppName, - PyTypeObject *flagsType = nullptr); - - /** - * Creates a new enum item for a given enum type and adds it to \p module. - * \param enumType Enum type to where the new enum item will be added. - * \param module Module to where the enum type of the new enum item belongs. - * \param itemName Name of the enum item. - * \param itemValue Numerical value of the enum item. - * \return true if everything goes fine, false if it fails. - */ - LIBSHIBOKEN_API bool createGlobalEnumItem(PyTypeObject *enumType, PyObject *module, const char *itemName, long itemValue); - /// This function does the same as createGlobalEnumItem, but adds the enum to a Shiboken type or namespace. - LIBSHIBOKEN_API bool createScopedEnumItem(PyTypeObject *enumType, PyTypeObject *scope, - const char *itemName, long itemValue); - LIBSHIBOKEN_API bool createScopedEnumItem(PyTypeObject *enumType, SbkObjectType *scope, const char *itemName, long itemValue); - - LIBSHIBOKEN_API PyObject *newItem(PyTypeObject *enumType, long itemValue, const char *itemName = nullptr); - - LIBSHIBOKEN_API PyTypeObject *newTypeWithName(const char *name, const char *cppName, - PyTypeObject *numbers_fromFlag=nullptr); - LIBSHIBOKEN_API const char *getCppName(PyTypeObject *type); - - LIBSHIBOKEN_API long getValue(PyObject *enumItem); - LIBSHIBOKEN_API PyObject *getEnumItemFromValue(PyTypeObject *enumType, long itemValue); - - /// Sets the enum's type converter. - LIBSHIBOKEN_API void setTypeConverter(PyTypeObject *enumType, SbkConverter *converter); - /// Returns the converter assigned to the enum \p type. - LIBSHIBOKEN_API SbkConverter *getTypeConverter(PyTypeObject *enumType); - - LIBSHIBOKEN_API PyObject *unpickleEnum(PyObject *, PyObject *); -} - -} // namespace Shiboken - -#endif // SKB_PYENUM_H diff --git a/sources/shiboken2/libshiboken/sbkmodule.cpp b/sources/shiboken2/libshiboken/sbkmodule.cpp deleted file mode 100644 index e5f4e2f88..000000000 --- a/sources/shiboken2/libshiboken/sbkmodule.cpp +++ /dev/null @@ -1,107 +0,0 @@ -/**************************************************************************** -** -** Copyright (C) 2016 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$ -** -****************************************************************************/ - -#include "sbkmodule.h" -#include "basewrapper.h" -#include "bindingmanager.h" -#include <unordered_map> - -/// This hash maps module objects to arrays of Python types. -using ModuleTypesMap = std::unordered_map<PyObject *, PyTypeObject **> ; - -/// This hash maps module objects to arrays of converters. -using ModuleConvertersMap = std::unordered_map<PyObject *, SbkConverter **>; - -/// All types produced in imported modules are mapped here. -static ModuleTypesMap moduleTypes; -static ModuleConvertersMap moduleConverters; - -namespace Shiboken -{ -namespace Module -{ - -PyObject *import(const char *moduleName) -{ - PyObject *sysModules = PyImport_GetModuleDict(); - PyObject *module = PyDict_GetItemString(sysModules, moduleName); - if (module) - Py_INCREF(module); - else - module = PyImport_ImportModule(moduleName); - - if (!module) - PyErr_Format(PyExc_ImportError,"could not import module '%s'", moduleName); - - return module; -} - -PyObject *create(const char *moduleName, void *moduleData) -{ - Shiboken::init(); - return PyModule_Create(reinterpret_cast<PyModuleDef *>(moduleData)); -} - -void registerTypes(PyObject *module, PyTypeObject **types) -{ - auto iter = moduleTypes.find(module); - if (iter == moduleTypes.end()) - moduleTypes.insert(std::make_pair(module, types)); -} - -PyTypeObject **getTypes(PyObject *module) -{ - auto iter = moduleTypes.find(module); - return (iter == moduleTypes.end()) ? 0 : iter->second; -} - -void registerTypeConverters(PyObject *module, SbkConverter **converters) -{ - auto iter = moduleConverters.find(module); - if (iter == moduleConverters.end()) - moduleConverters.insert(std::make_pair(module, converters)); -} - -SbkConverter **getTypeConverters(PyObject *module) -{ - auto iter = moduleConverters.find(module); - return (iter == moduleConverters.end()) ? 0 : iter->second; -} - -} } // namespace Shiboken::Module diff --git a/sources/shiboken2/libshiboken/sbkmodule.h b/sources/shiboken2/libshiboken/sbkmodule.h deleted file mode 100644 index 02e4a2706..000000000 --- a/sources/shiboken2/libshiboken/sbkmodule.h +++ /dev/null @@ -1,99 +0,0 @@ -/**************************************************************************** -** -** Copyright (C) 2016 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$ -** -****************************************************************************/ - -#ifndef SBK_MODULE_H -#define SBK_MODULE_H - -#include "sbkpython.h" -#include "shibokenmacros.h" - -extern "C" -{ -struct SbkConverter; -} - -namespace Shiboken { -namespace Module { - -/** - * Imports and returns the module named \p moduleName, or a NULL pointer in case of failure. - * If the module is already imported, it increments its reference count before returning it. - * \returns the module specified in \p moduleName or NULL if an error occurs. - */ -LIBSHIBOKEN_API PyObject *import(const char *moduleName); - -/** - * Creates a new Python module named \p moduleName using the information passed in \p moduleData. - * In fact, \p moduleData expects a "PyMethodDef *" object, but that's for Python 2. A "void*" - * was preferred to make this work with future Python 3 support. - * \returns a newly created module. - */ -LIBSHIBOKEN_API PyObject *create(const char *moduleName, void *moduleData); - -/** - * Registers the list of types created by \p module. - * \param module Module where the types were created. - * \param types Array of PyTypeObject *objects representing the types created on \p module. - */ -LIBSHIBOKEN_API void registerTypes(PyObject *module, PyTypeObject **types); - -/** - * Retrieves the array of types. - * \param module Module where the types were created. - * \returns A pointer to the PyTypeObject *array of types. - */ -LIBSHIBOKEN_API PyTypeObject **getTypes(PyObject *module); - -/** - * Registers the list of converters created by \p module for non-wrapper types. - * \param module Module where the converters were created. - * \param converters Array of SbkConverter *objects representing the converters created on \p module. - */ -LIBSHIBOKEN_API void registerTypeConverters(PyObject *module, SbkConverter **converters); - -/** - * Retrieves the array of converters. - * \param module Module where the converters were created. - * \returns A pointer to the SbkConverter *array of converters. - */ -LIBSHIBOKEN_API SbkConverter **getTypeConverters(PyObject *module); - -} } // namespace Shiboken::Module - -#endif // SBK_MODULE_H diff --git a/sources/shiboken2/libshiboken/sbknumpyarrayconverter.cpp b/sources/shiboken2/libshiboken/sbknumpyarrayconverter.cpp deleted file mode 100644 index 996968fa1..000000000 --- a/sources/shiboken2/libshiboken/sbknumpyarrayconverter.cpp +++ /dev/null @@ -1,308 +0,0 @@ -/**************************************************************************** -** -** Copyright (C) 2017 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$ -** -****************************************************************************/ - -#include "sbkarrayconverter.h" -#include "helper.h" -#include "sbkconverter.h" -#include "sbkconverter_p.h" -#include "sbkarrayconverter_p.h" - -#include <numpy/arrayobject.h> - -#include <algorithm> -#include <iostream> -#include <cstdint> - -enum { debugNumPy = 0 }; - -struct TypeCharMapping -{ - NPY_TYPES type; - const char *name; -}; - -static const TypeCharMapping typeCharMappings[] = { -{NPY_BYTE, "NPY_BYTE"}, -{NPY_UBYTE, "NPY_UBYTE"}, -{NPY_SHORT, "NPY_SHORT"}, -{NPY_USHORT, "NPY_USHORT"}, -{NPY_INT, "NPY_INT"}, -{NPY_UINT, "NPY_UINT"}, -{NPY_LONG, "NPY_LONG"}, -{NPY_ULONG, "NPY_ULONG"}, -{NPY_LONGLONG, "NPY_LONGLONG"}, -{NPY_ULONGLONG, "NPY_ULONGLONG"}, -{NPY_FLOAT, "NPY_FLOAT"}, -{NPY_DOUBLE, "NPY_DOUBLE"} -}; - -const char *npTypeName(npy_intp t) -{ - const TypeCharMapping *end = typeCharMappings + sizeof(typeCharMappings) / sizeof(typeCharMappings[0]); - const TypeCharMapping *result = - std::find_if(typeCharMappings, end, - [t] (const TypeCharMapping &m) { return m.type == t; }); - return result != end ? result->name : nullptr; -} - -std::ostream &operator<<(std::ostream &str, PyArrayObject *o) -{ - str << "PyArrayObject("; - if (o) { - const npy_intp npType = PyArray_TYPE(o); - if (const char *name = npTypeName(npType)) - str << name; - else - str << "type=" << npType; - const int nDim = PyArray_NDIM(o); - const npy_intp *dims = PyArray_DIMS(o); - for (int d = 0; d < nDim; ++d) - str << '[' << dims[d] << ']'; - str << ", "; - const int flags = PyArray_FLAGS(o); - if ((flags & NPY_ARRAY_C_CONTIGUOUS) != 0) - str << " NPY_ARRAY_C_CONTIGUOUS"; - if ((flags & NPY_ARRAY_F_CONTIGUOUS) != 0) - str << " NPY_ARRAY_F_CONTIGUOUS"; - if ((flags & NPY_ARRAY_OWNDATA) != 0) - str << " NPY_ARRAY_OWNDATA"; - if ((flags & NPY_ARRAY_FORCECAST) != 0) - str << " NPY_ARRAY_FORCECAST"; - if ((flags & NPY_ARRAY_ENSURECOPY) != 0) - str << " NPY_ARRAY_ENSURECOPY"; - if ((flags & NPY_ARRAY_ENSUREARRAY) != 0) - str << " NPY_ARRAY_ENSUREARRAY"; - if ((flags & NPY_ARRAY_ELEMENTSTRIDES) != 0) - str << " NPY_ARRAY_ELEMENTSTRIDES"; - if ((flags & NPY_ARRAY_ALIGNED) != 0) - str << " NPY_ARRAY_ALIGNED"; - if ((flags & NPY_ARRAY_NOTSWAPPED) != 0) - str << " NPY_ARRAY_NOTSWAPPED"; - if ((flags & NPY_ARRAY_WRITEABLE) != 0) - str << " NPY_ARRAY_WRITEABLE"; - if ((flags & NPY_ARRAY_UPDATEIFCOPY) != 0) - str << " NPY_ARRAY_UPDATEIFCOPY"; - } else { - str << '0'; - } - str << ')'; - return str; -} - -namespace Shiboken { -namespace Conversions { - -// Internals from sbkarrayconverter.cpp -SbkArrayConverter *createArrayConverter(IsArrayConvertibleToCppFunc toCppCheckFunc); -void setArrayTypeConverter(int index, int dimension, SbkArrayConverter *c); -SbkArrayConverter *unimplementedArrayConverter(); - -template <int dimension> -static bool isPrimitiveArray(PyObject *pyIn, int expectedNpType) -{ - if (!PyArray_Check(pyIn)) - return false; - auto *pya = reinterpret_cast<PyArrayObject *>(pyIn); - if (debugNumPy) { - std::cerr << __FUNCTION__ << "(expectedNpType=" << expectedNpType; - if (const char *name = npTypeName(expectedNpType)) - std::cerr << " (" << name << ')'; - std::cerr << ' ' << pya << '\n'; - } - - const int dim = PyArray_NDIM(pya); - if (dim != dimension) { - warning(PyExc_RuntimeWarning, 0, - "%d dimensional numpy array passed to a function expecting a %d dimensional array.", - dim, dimension); - return false; - } - if ((PyArray_FLAGS(pya) & NPY_ARRAY_C_CONTIGUOUS) == 0) { - warning(PyExc_RuntimeWarning, 0, - "Cannot handle numpy arrays that do not have NPY_ARRAY_C_CONTIGUOUS set."); - return false; - } - const int actualNpType = PyArray_TYPE(pya); - if (actualNpType != expectedNpType) { - const char *actualName = npTypeName(actualNpType); - const char *expectedName = npTypeName(expectedNpType); - warning(PyExc_RuntimeWarning, 0, - "A numpy array of type %d (%s) was passed to a function expecting type %d (%s).", - actualNpType, actualName ? actualName : "", - expectedNpType, expectedName ? expectedName : ""); - return false; - } - return true; -} - -static inline bool primitiveArrayCheck1(PyObject *pyIn, int expectedNpType, int expectedSize) -{ - if (!isPrimitiveArray<1>(pyIn, expectedNpType)) - return false; - if (expectedSize >= 0) { - auto *pya = reinterpret_cast<PyArrayObject *>(pyIn); - const int size = int(PyArray_DIMS(pya)[0]); - if (size < expectedSize) { - warning(PyExc_RuntimeWarning, 0, "A numpy array of size %d was passed to a function expects %d.", - size, expectedSize); - return false; - } - } - return true; -} - -// Convert one-dimensional array -template <class T> -static void convertArray1(PyObject *pyIn, void *cppOut) -{ - auto *handle = reinterpret_cast<ArrayHandle<T> *>(cppOut); - auto *pya = reinterpret_cast<PyArrayObject *>(pyIn); - const npy_intp size = PyArray_DIMS(pya)[0]; - if (debugNumPy) - std::cerr << __FUNCTION__ << ' ' << size << '\n'; - handle->setData(reinterpret_cast<T *>(PyArray_DATA(pya)), size_t(size)); -} - -// Convert 2 dimensional array -template <class T> -static void convertArray2(PyObject *pyIn, void *cppOut) -{ - typedef typename Array2Handle<T, 1>::RowType RowType; - auto *handle = reinterpret_cast<Array2Handle<T, 1> *>(cppOut); - auto *pya = reinterpret_cast<PyArrayObject *>(pyIn); - handle->setData(reinterpret_cast<RowType *>(PyArray_DATA(pya))); -} - -template <class T, int NumPyType> -static PythonToCppFunc checkArray1(PyObject *pyIn, int dim1, int /* dim2 */) -{ - return primitiveArrayCheck1(pyIn, NumPyType, dim1) ? convertArray1<T> : nullptr; -} - -static inline bool primitiveArrayCheck2(PyObject *pyIn, int expectedNpType, int expectedDim1, int expectedDim2) -{ - if (!isPrimitiveArray<2>(pyIn, expectedNpType)) - return false; - if (expectedDim2 >= 0) { - auto *pya = reinterpret_cast<PyArrayObject *>(pyIn); - const int dim1 = int(PyArray_DIMS(pya)[0]); - const int dim2 = int(PyArray_DIMS(pya)[1]); - if (dim1 != expectedDim1 || dim2 != expectedDim2) { - warning(PyExc_RuntimeWarning, 0, "A numpy array of size %dx%d was passed to a function that expects %dx%d.", - dim1, dim2, expectedDim1, expectedDim2); - return false; - } - } - return true; -} - -template <class T, int NumPyType> -static PythonToCppFunc checkArray2(PyObject *pyIn, int dim1, int dim2) -{ - return primitiveArrayCheck2(pyIn, NumPyType, dim1, dim2) ? convertArray2<T> : nullptr; -} - -template <class T> -static void setOrExtendArrayConverter(int dimension, IsArrayConvertibleToCppFunc toCppCheckFunc) -{ - SbkArrayConverter *arrayConverter = ArrayTypeConverter<T>(dimension); - if (arrayConverter == unimplementedArrayConverter()) { - arrayConverter = createArrayConverter(toCppCheckFunc); - setArrayTypeConverter(ArrayTypeIndex<T>::index, dimension, arrayConverter); - } else { - arrayConverter->toCppConversions.push_back(toCppCheckFunc); - } -} - -// Extend the converters for primitive type one-dimensional arrays by NumPy ones. -template <class T, int NumPyType> -static inline void extendArrayConverter1() -{ - setOrExtendArrayConverter<T>(1, checkArray1<T, NumPyType>); -} - -// Extend the converters for primitive type one-dimensional arrays by NumPy ones. -template <class T, int NumPyType> -static inline void extendArrayConverter2() -{ - setOrExtendArrayConverter<T>(2, checkArray2<T, NumPyType>); -} - -void initNumPyArrayConverters() -{ - // Expanded from macro "import_array" in __multiarray_api.h - // Make sure to read about the magic defines PY_ARRAY_UNIQUE_SYMBOL etc., - // when changing this or spreading the code over several source files. - if (_import_array() < 0) { - if (debugNumPy) - PyErr_Print(); - PyErr_Clear(); - return; - } - // Extend the converters for primitive types by NumPy ones. - extendArrayConverter1<short, NPY_SHORT>(); - extendArrayConverter2<short, NPY_SHORT>(); - extendArrayConverter1<unsigned short, NPY_SHORT>(); - extendArrayConverter2<unsigned short, NPY_SHORT>(); - extendArrayConverter1<int, NPY_INT>(); - extendArrayConverter2<int, NPY_INT>(); - extendArrayConverter1<unsigned int, NPY_UINT>(); - extendArrayConverter2<unsigned int, NPY_UINT>(); - extendArrayConverter1<long long, NPY_LONGLONG>(); - extendArrayConverter2<long long, NPY_LONGLONG>(); - extendArrayConverter1<unsigned long long, NPY_ULONGLONG>(); - if (sizeof(long) == 8) { // UNIX/LP64: ints typically come as long - extendArrayConverter1<long long, NPY_LONG>(); - extendArrayConverter2<long long, NPY_LONG>(); - extendArrayConverter1<unsigned long long, NPY_ULONG>(); - extendArrayConverter2<unsigned long long, NPY_ULONG>(); - } else if (sizeof(long) == sizeof(int)) { - extendArrayConverter1<int, NPY_LONG>(); - extendArrayConverter1<unsigned, NPY_ULONG>(); - extendArrayConverter2<int, NPY_LONG>(); - extendArrayConverter2<unsigned, NPY_ULONG>(); - } - extendArrayConverter1<float, NPY_FLOAT>(); - extendArrayConverter2<float, NPY_FLOAT>(); - extendArrayConverter1<double, NPY_DOUBLE>(); - extendArrayConverter2<double, NPY_DOUBLE>(); -} - -} // namespace Conversions -} // namespace Shiboken diff --git a/sources/shiboken2/libshiboken/sbkpython.h b/sources/shiboken2/libshiboken/sbkpython.h deleted file mode 100644 index abdb02eba..000000000 --- a/sources/shiboken2/libshiboken/sbkpython.h +++ /dev/null @@ -1,130 +0,0 @@ -/**************************************************************************** -** -** Copyright (C) 2018 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$ -** -****************************************************************************/ - -#ifndef SBKPYTHON_H -#define SBKPYTHON_H - -#include "sbkversion.h" -#define PyEnumMeta_Check(x) (strcmp(Py_TYPE(x)->tp_name, "EnumMeta") == 0) - -// Qt's "slots" macro collides with the "slots" member variables -// used in some Python structs. For compilers that support push_macro, -// temporarily undefine it. -#if defined(slots) && (defined(__GNUC__) || defined(_MSC_VER) || defined(__clang__)) -# pragma push_macro("slots") -# undef slots -/* - * Python 2 has function _Py_Mangle directly in Python.h . - * This creates wrong language binding unless we define 'extern "C"' here. - */ -extern "C" { -/* - * Python 2 uses the "register" keyword, which is deprecated in C++ 11 - * and forbidden in C++17. - */ -# if defined(__clang__) -# pragma clang diagnostic push -# pragma clang diagnostic ignored "-Wdeprecated-register" -# endif - -# include <Python.h> - -# if defined(__clang__) -# pragma clang diagnostic pop -# endif -} -# include <structmember.h> -// Now we have the usual variables from Python.h . -# include "python25compat.h" -# include "shibokenmacros.h" -// "pep384impl.h" may nowhere be included but in this file. -# include "pep384impl.h" -# pragma pop_macro("slots") - -#else - -extern "C" { -/* - * Python 2 uses the "register" keyword, which is deprecated in C++ 11 - * and forbidden in C++17. - */ -# if defined(__clang__) -# pragma clang diagnostic push -# pragma clang diagnostic ignored "-Wdeprecated-register" -# endif - -# include <Python.h> - -# if defined(__clang__) -# pragma clang diagnostic pop -# endif -} -# include <structmember.h> -// Now we have the usual variables from Python.h . -# include "python25compat.h" -# include "shibokenmacros.h" -// "pep384impl.h" may nowhere be included but in this file. -# include "pep384impl.h" -#endif - -#define PyInt_Type PyLong_Type -#define PyInt_Check PyLong_Check -#define PyInt_CheckExact PyLong_CheckExact -#define PyInt_FromString PyLong_FromString -#define PyInt_FromSsize_t PyLong_FromSsize_t -#define PyInt_FromSize_t PyLong_FromSize_t -#define PyInt_AS_LONG PyLong_AS_LONG -#define PyInt_AsUnsignedLongLongMask PyLong_AsLongLong -#define PyInt_FromLong PyLong_FromLong -#define PyInt_AsLong PyLong_AsLong -#define SbkNumber_Check PyNumber_Check -#define Py_TPFLAGS_CHECKTYPES 0 - -#define SBK_NB_BOOL(x) (x).nb_bool -#define SBK_PyMethod_New PyMethod_New -#define PyInt_AsSsize_t(x) PyLong_AsSsize_t(x) -#define PyString_Type PyUnicode_Type - -// In Python 3, Py_TPFLAGS_DEFAULT contains Py_TPFLAGS_HAVE_VERSION_TAG, -// which will trigger the attribute cache, which is not intended in Qt for Python. -// Use a customized Py_TPFLAGS_DEFAULT by defining Py_TPFLAGS_HAVE_VERSION_TAG = 0. -#undef Py_TPFLAGS_HAVE_VERSION_TAG -#define Py_TPFLAGS_HAVE_VERSION_TAG (0) - -#endif diff --git a/sources/shiboken2/libshiboken/sbkstaticstrings.cpp b/sources/shiboken2/libshiboken/sbkstaticstrings.cpp deleted file mode 100644 index 5559d58d6..000000000 --- a/sources/shiboken2/libshiboken/sbkstaticstrings.cpp +++ /dev/null @@ -1,108 +0,0 @@ -/**************************************************************************** -** -** 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$ -** -****************************************************************************/ - -#include "sbkstaticstrings.h" -#include "sbkstaticstrings_p.h" -#include "sbkstring.h" - -#define STATIC_STRING_IMPL(funcName, value) \ -PyObject *funcName() \ -{ \ - static PyObject *const s = Shiboken::String::createStaticString(value); \ - return s; \ -} - -namespace Shiboken -{ -namespace PyName { -// exported: -STATIC_STRING_IMPL(dumps, "dumps") -STATIC_STRING_IMPL(fget, "fget") -STATIC_STRING_IMPL(fset, "fset") -STATIC_STRING_IMPL(loads, "loads") -STATIC_STRING_IMPL(multi, "multi") -STATIC_STRING_IMPL(name, "name") -STATIC_STRING_IMPL(result, "result") -STATIC_STRING_IMPL(value, "value") -STATIC_STRING_IMPL(values, "values") - -// Internal: -STATIC_STRING_IMPL(classmethod, "classmethod") -STATIC_STRING_IMPL(co_name, "co_name") -STATIC_STRING_IMPL(compile, "compile"); -STATIC_STRING_IMPL(f_code, "f_code") -STATIC_STRING_IMPL(f_lineno, "f_lineno") -STATIC_STRING_IMPL(function, "function") -STATIC_STRING_IMPL(marshal, "marshal") -STATIC_STRING_IMPL(method, "method") -STATIC_STRING_IMPL(mro, "mro") -STATIC_STRING_IMPL(overload, "overload") -STATIC_STRING_IMPL(staticmethod, "staticmethod") -} // namespace PyName - -namespace PyMagicName { -// exported: -STATIC_STRING_IMPL(class_, "__class__") -STATIC_STRING_IMPL(dict, "__dict__") -STATIC_STRING_IMPL(doc, "__doc__") -STATIC_STRING_IMPL(ecf, "__ecf__") -STATIC_STRING_IMPL(file, "__file__") -STATIC_STRING_IMPL(get, "__get__") -STATIC_STRING_IMPL(members, "__members__") -STATIC_STRING_IMPL(module, "__module__") -STATIC_STRING_IMPL(name, "__name__") -STATIC_STRING_IMPL(qualname, "__qualname__") -STATIC_STRING_IMPL(self, "__self__") - -// Internal: -STATIC_STRING_IMPL(base, "__base__") -STATIC_STRING_IMPL(bases, "__bases__") -STATIC_STRING_IMPL(builtins, "__builtins__") -STATIC_STRING_IMPL(code, "__code__") -STATIC_STRING_IMPL(dictoffset, "__dictoffset__") -STATIC_STRING_IMPL(func, "__func__") -STATIC_STRING_IMPL(func_kind, "__func_kind__") -STATIC_STRING_IMPL(iter, "__iter__") -STATIC_STRING_IMPL(mro, "__mro__") -STATIC_STRING_IMPL(new_, "__new__") -STATIC_STRING_IMPL(objclass, "__objclass__") -STATIC_STRING_IMPL(signature, "__signature__") -STATIC_STRING_IMPL(weakrefoffset, "__weakrefoffset__") -} // namespace PyMagicName -} // namespace Shiboken diff --git a/sources/shiboken2/libshiboken/sbkstaticstrings.h b/sources/shiboken2/libshiboken/sbkstaticstrings.h deleted file mode 100644 index 16d36041e..000000000 --- a/sources/shiboken2/libshiboken/sbkstaticstrings.h +++ /dev/null @@ -1,82 +0,0 @@ -/**************************************************************************** -** -** 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$ -** -****************************************************************************/ - -#ifndef SBKSTATICSTRINGS_H -#define SBKSTATICSTRINGS_H - -#include "sbkpython.h" -#include "shibokenmacros.h" - -namespace Shiboken -{ -// Some often-used strings -namespace PyName -{ -LIBSHIBOKEN_API PyObject *co_name(); -LIBSHIBOKEN_API PyObject *dumps(); -LIBSHIBOKEN_API PyObject *fget(); -LIBSHIBOKEN_API PyObject *fset(); -LIBSHIBOKEN_API PyObject *f_code(); -LIBSHIBOKEN_API PyObject *f_lineno(); -LIBSHIBOKEN_API PyObject *loads(); -LIBSHIBOKEN_API PyObject *multi(); -LIBSHIBOKEN_API PyObject *name(); -LIBSHIBOKEN_API PyObject *result(); -LIBSHIBOKEN_API PyObject *value(); -LIBSHIBOKEN_API PyObject *values(); -} // namespace PyName - -namespace PyMagicName -{ -LIBSHIBOKEN_API PyObject *class_(); -LIBSHIBOKEN_API PyObject *dict(); -LIBSHIBOKEN_API PyObject *doc(); -LIBSHIBOKEN_API PyObject *ecf(); -LIBSHIBOKEN_API PyObject *file(); -LIBSHIBOKEN_API PyObject *func(); -LIBSHIBOKEN_API PyObject *get(); -LIBSHIBOKEN_API PyObject *members(); -LIBSHIBOKEN_API PyObject *module(); -LIBSHIBOKEN_API PyObject *name(); -LIBSHIBOKEN_API PyObject *qualname(); -LIBSHIBOKEN_API PyObject *self(); -} // namespace PyMagicName -} // namespace Shiboken - -#endif // SBKSTATICSTRINGS_H diff --git a/sources/shiboken2/libshiboken/sbkstaticstrings_p.h b/sources/shiboken2/libshiboken/sbkstaticstrings_p.h deleted file mode 100644 index acfc71409..000000000 --- a/sources/shiboken2/libshiboken/sbkstaticstrings_p.h +++ /dev/null @@ -1,72 +0,0 @@ -/**************************************************************************** -** -** 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$ -** -****************************************************************************/ - -#include "sbkpython.h" -#include "shibokenmacros.h" - -namespace Shiboken -{ -namespace PyName -{ -PyObject *classmethod(); -PyObject *compile(); -PyObject *function(); -PyObject *marshal(); -PyObject *method(); -PyObject *mro(); -PyObject *overload(); -PyObject *staticmethod(); -} // namespace PyName -namespace PyMagicName -{ -PyObject *base(); -PyObject *bases(); -PyObject *builtins(); -PyObject *code(); -PyObject *dictoffset(); -PyObject *func_kind(); -PyObject *iter(); -PyObject *module(); -PyObject *mro(); -PyObject *new_(); -PyObject *objclass(); -PyObject *signature(); -PyObject *weakrefoffset(); -} // namespace PyMagicName -} // namespace Shiboken diff --git a/sources/shiboken2/libshiboken/sbkstring.cpp b/sources/shiboken2/libshiboken/sbkstring.cpp deleted file mode 100644 index ca32f5919..000000000 --- a/sources/shiboken2/libshiboken/sbkstring.cpp +++ /dev/null @@ -1,290 +0,0 @@ -/**************************************************************************** -** -** 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$ -** -****************************************************************************/ - -#include "sbkstring.h" -#include "sbkstaticstrings_p.h" -#include "autodecref.h" - -#include <vector> -#include <unordered_set> - -namespace Shiboken -{ - -namespace String -{ - -// PYSIDE-795: Redirecting PySequence to Iterable -bool checkIterable(PyObject *obj) -{ - return PyObject_HasAttr(obj, Shiboken::PyMagicName::iter()); -} - -bool checkType(PyTypeObject *type) -{ - return type == &PyUnicode_Type; -} - -bool check(PyObject *obj) -{ - return obj == Py_None || PyUnicode_Check(obj); -} - -bool checkChar(PyObject *pyobj) -{ - return check(pyobj) && (len(pyobj) == 1); -} - -bool isConvertible(PyObject *obj) -{ - return check(obj); -} - -PyObject *fromCString(const char *value) -{ - return PyUnicode_FromString(value); -} - -PyObject *fromCString(const char *value, int len) -{ - return PyUnicode_FromStringAndSize(value, len); -} - -const char *toCString(PyObject *str, Py_ssize_t *len) -{ - if (str == Py_None) - return nullptr; - if (PyUnicode_Check(str)) { - if (len) { - // We need to encode the unicode string into utf8 to know the size of returned char *. - Shiboken::AutoDecRef uniStr(PyUnicode_AsUTF8String(str)); - *len = PyBytes_GET_SIZE(uniStr.object()); - } - // Return unicode from str instead of uniStr, because the lifetime of the returned pointer - // depends on the lifetime of str. - return _PepUnicode_AsString(str); - } - if (PyBytes_Check(str)) { - if (len) - *len = PyBytes_GET_SIZE(str); - return PyBytes_AS_STRING(str); - } - return nullptr; -} - -bool concat(PyObject **val1, PyObject *val2) -{ - if (PyUnicode_Check(*val1) && PyUnicode_Check(val2)) { - PyObject *result = PyUnicode_Concat(*val1, val2); - Py_DECREF(*val1); - *val1 = result; - return true; - } - - if (PyBytes_Check(*val1) && PyBytes_Check(val2)) { - PyBytes_Concat(val1, val2); - return true; - } - - return false; -} - -PyObject *fromFormat(const char *format, ...) -{ - va_list argp; - va_start(argp, format); - PyObject *result = nullptr; - result = PyUnicode_FromFormatV(format, argp); - va_end(argp); - return result; -} - -PyObject *fromStringAndSize(const char *str, Py_ssize_t size) -{ - return PyUnicode_FromStringAndSize(str, size); -} - -int compare(PyObject *val1, const char *val2) -{ - if (PyUnicode_Check(val1)) - return PyUnicode_CompareWithASCIIString(val1, val2); - return 0; - -} - -Py_ssize_t len(PyObject *str) -{ - if (str == Py_None) - return 0; - - if (PyUnicode_Check(str)) - return PepUnicode_GetLength(str); - - if (PyBytes_Check(str)) - return PyBytes_GET_SIZE(str); - return 0; -} - -/////////////////////////////////////////////////////////////////////// -// -// Implementation of efficient Python strings -// ------------------------------------------ -// -// Instead of repetitively executing -// -// PyObject *attr = PyObject_GetAttrString(obj, "__name__"); -// -// a helper of the form -// -// PyObject *name() -// { -// static PyObject *const s = Shiboken::String::createStaticString("__name__"); -// return result; -// } -// -// can now be implemented, which registers the string into a static set avoiding -// repetitive string creation. The resulting code looks like: -// -// PyObject *attr = PyObject_GetAttr(obj, name()); -// - -using StaticStrings = std::unordered_set<PyObject *>; - -static void finalizeStaticStrings(); // forward - -static StaticStrings &staticStrings() -{ - static StaticStrings result; - return result; -} - -static void finalizeStaticStrings() -{ - auto &set = staticStrings(); - for (PyObject *ob : set) { - Py_REFCNT(ob) = 1; - Py_DECREF(ob); - } - set.clear(); -} - -PyObject *createStaticString(const char *str) -{ - static bool initialized = false; - if (!initialized) { - Py_AtExit(finalizeStaticStrings); - initialized = true; - } -#if PY_VERSION_HEX >= 0x03000000 - PyObject *result = PyUnicode_InternFromString(str); -#else - PyObject *result = PyString_InternFromString(str); -#endif - if (result == nullptr) { - // This error is never checked, but also very unlikely. Report and exit. - PyErr_Print(); - Py_FatalError("unexpected error in createStaticString()"); - } - auto it = staticStrings().find(result); - if (it == staticStrings().end()) - staticStrings().insert(result); - /* - * Note: We always add one reference even if we have a new string. - * This makes the strings immortal, and we are safe if someone - * uses AutoDecRef, although the set cannot cope with deletions. - * The exit handler cleans that up, anyway. - */ - Py_INCREF(result); - return result; -} - -/////////////////////////////////////////////////////////////////////// -// -// PYSIDE-1019: Helper function for snake_case vs. camelCase names -// --------------------------------------------------------------- -// -// When renaming dict entries, `BindingManager::getOverride` must -// use adapted names. -// -// This might become more complex when we need to register -// exceptions from this rule. -// - -PyObject *getSnakeCaseName(const char *name, bool lower) -{ - /* - * Convert `camelCase` to `snake_case`. - * Gives up when there are two consecutive upper chars. - * - * Also functions beginning with `gl` followed by upper case stay - * unchanged since that are the special OpenGL functions. - */ - if (!lower - || strlen(name) < 3 - || (name[0] == 'g' && name[1] == 'l' && isupper(name[2]))) - return createStaticString(name); - - char new_name[200 + 1] = {}; - const char *p = name; - char *q = new_name; - for (; *p && q - new_name < 200; ++p, ++q) { - if (isupper(*p)) { - if (p != name && isupper(*(p - 1))) - return createStaticString(name); - *q = '_'; - ++q; - *q = tolower(*p); - } - else { - *q = *p; - } - } - return createStaticString(new_name); -} - -PyObject *getSnakeCaseName(PyObject *name, bool lower) -{ - // This is all static strings, not refcounted. - if (lower) - return getSnakeCaseName(toCString(name), lower); - return name; -} - -} // namespace String -} // namespace Shiboken diff --git a/sources/shiboken2/libshiboken/sbkstring.h b/sources/shiboken2/libshiboken/sbkstring.h deleted file mode 100644 index 817b8acc2..000000000 --- a/sources/shiboken2/libshiboken/sbkstring.h +++ /dev/null @@ -1,73 +0,0 @@ -/**************************************************************************** -** -** 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$ -** -****************************************************************************/ - -#ifndef SBKSTRING_H -#define SBKSTRING_H - -#include "sbkpython.h" -#include "shibokenmacros.h" - -namespace Shiboken -{ -namespace String -{ - LIBSHIBOKEN_API bool check(PyObject *obj); - LIBSHIBOKEN_API bool checkIterable(PyObject *obj); - LIBSHIBOKEN_API bool checkType(PyTypeObject *obj); - LIBSHIBOKEN_API bool checkChar(PyObject *obj); - LIBSHIBOKEN_API bool isConvertible(PyObject *obj); - LIBSHIBOKEN_API PyObject *fromCString(const char *value); - LIBSHIBOKEN_API PyObject *fromCString(const char *value, int len); - LIBSHIBOKEN_API const char *toCString(PyObject *str, Py_ssize_t *len = nullptr); - LIBSHIBOKEN_API bool concat(PyObject **val1, PyObject *val2); - LIBSHIBOKEN_API PyObject *fromFormat(const char *format, ...); - LIBSHIBOKEN_API PyObject *fromStringAndSize(const char *str, Py_ssize_t size); - LIBSHIBOKEN_API int compare(PyObject *val1, const char *val2); - LIBSHIBOKEN_API Py_ssize_t len(PyObject *str); - LIBSHIBOKEN_API PyObject *createStaticString(const char *str); - LIBSHIBOKEN_API PyObject *getSnakeCaseName(const char *name, bool lower); - LIBSHIBOKEN_API PyObject *getSnakeCaseName(PyObject *name, bool lower); - -} // namespace String -} // namespace Shiboken - - -#endif - - diff --git a/sources/shiboken2/libshiboken/sbkversion.h.in b/sources/shiboken2/libshiboken/sbkversion.h.in deleted file mode 100644 index 99ee7f93e..000000000 --- a/sources/shiboken2/libshiboken/sbkversion.h.in +++ /dev/null @@ -1,53 +0,0 @@ -/**************************************************************************** -** -** Copyright (C) 2016 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$ -** -****************************************************************************/ - -#ifndef SBKVERSION_H -#define SBKVERSION_H - -#define SHIBOKEN_VERSION "@shiboken_MAJOR_VERSION@.@shiboken_MINOR_VERSION@.@shiboken_MICRO_VERSION@" -#define SHIBOKEN_MAJOR_VERSION @shiboken_MAJOR_VERSION@ -#define SHIBOKEN_MINOR_VERSION @shiboken_MINOR_VERSION@ -#define SHIBOKEN_MICRO_VERSION @shiboken_MICRO_VERSION@ -#define SHIBOKEN_RELEASE_LEVEL "final" -#define SHIBOKEN_SERIAL 0 -#define PYTHON_VERSION_MAJOR @PYTHON_VERSION_MAJOR@ -#define PYTHON_VERSION_MINOR @PYTHON_VERSION_MINOR@ -#define PYTHON_VERSION_PATCH @PYTHON_VERSION_PATCH@ - -#endif diff --git a/sources/shiboken2/libshiboken/shiboken.h b/sources/shiboken2/libshiboken/shiboken.h deleted file mode 100644 index 3e1df5235..000000000 --- a/sources/shiboken2/libshiboken/shiboken.h +++ /dev/null @@ -1,61 +0,0 @@ -/**************************************************************************** -** -** Copyright (C) 2016 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$ -** -****************************************************************************/ - -#ifndef SHIBOKEN_H -#define SHIBOKEN_H - -#include "sbkpython.h" -#include "autodecref.h" -#include "basewrapper.h" -#include "bindingmanager.h" -#include "gilstate.h" -#include "threadstatesaver.h" -#include "helper.h" -#include "sbkarrayconverter.h" -#include "sbkconverter.h" -#include "sbkenum.h" -#include "sbkmodule.h" -#include "sbkstring.h" -#include "sbkstaticstrings.h" -#include "shibokenmacros.h" -#include "shibokenbuffer.h" -#include "signature.h" - -#endif // SHIBOKEN_H - diff --git a/sources/shiboken2/libshiboken/shibokenbuffer.cpp b/sources/shiboken2/libshiboken/shibokenbuffer.cpp deleted file mode 100644 index 5bae38aa5..000000000 --- a/sources/shiboken2/libshiboken/shibokenbuffer.cpp +++ /dev/null @@ -1,83 +0,0 @@ -/**************************************************************************** -** -** Copyright (C) 2016 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$ -** -****************************************************************************/ - -#include "shibokenbuffer.h" -#include <cstdlib> -#include <cstring> - -bool Shiboken::Buffer::checkType(PyObject *pyObj) -{ - return PyObject_CheckBuffer(pyObj) != 0; -} - -void *Shiboken::Buffer::getPointer(PyObject *pyObj, Py_ssize_t *size) -{ - Py_buffer view; - if (PyObject_GetBuffer(pyObj, &view, PyBUF_ND) == 0) { - if (size) - *size = view.len; - PyBuffer_Release(&view); - return view.buf; - } - return nullptr; -} - -PyObject *Shiboken::Buffer::newObject(void *memory, Py_ssize_t size, Type type) -{ - if (size == 0) - Py_RETURN_NONE; - Py_buffer view; - memset(&view, 0, sizeof(Py_buffer)); - view.buf = memory; - view.len = size; - view.readonly = type == Shiboken::Buffer::ReadOnly; - view.ndim = 1; - view.itemsize = sizeof(char); - Py_ssize_t shape[] = { size }; - view.shape = shape; - // Pep384: This is way too complicated and impossible with the limited api: - //return PyMemoryView_FromBuffer(&view); - return PyMemoryView_FromMemory(reinterpret_cast<char *>(view.buf), - size, type == ReadOnly ? PyBUF_READ : PyBUF_WRITE); -} - -PyObject *Shiboken::Buffer::newObject(const void *memory, Py_ssize_t size) -{ - return newObject(const_cast<void *>(memory), size, ReadOnly); -} diff --git a/sources/shiboken2/libshiboken/shibokenbuffer.h b/sources/shiboken2/libshiboken/shibokenbuffer.h deleted file mode 100644 index dc9f8d89f..000000000 --- a/sources/shiboken2/libshiboken/shibokenbuffer.h +++ /dev/null @@ -1,85 +0,0 @@ -/**************************************************************************** -** -** Copyright (C) 2016 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$ -** -****************************************************************************/ - -#ifndef SHIBOKEN_BUFFER_H -#define SHIBOKEN_BUFFER_H - -#include "sbkpython.h" -#include "shibokenmacros.h" - -namespace Shiboken -{ - -namespace Buffer -{ - enum Type { - ReadOnly, - WriteOnly, - ReadWrite - }; - - /** - * Creates a new Python buffer pointing to a contiguous memory block at - * \p memory of size \p size. - */ - LIBSHIBOKEN_API PyObject *newObject(void *memory, Py_ssize_t size, Type type); - - /** - * Creates a new <b>read only</b> Python buffer pointing to a contiguous memory block at - * \p memory of size \p size. - */ - LIBSHIBOKEN_API PyObject *newObject(const void *memory, Py_ssize_t size); - - /** - * Check if is ok to use \p pyObj as argument in all function under Shiboken::Buffer namespace. - */ - LIBSHIBOKEN_API bool checkType(PyObject *pyObj); - - /** - * Returns a pointer to the memory pointed by the buffer \p pyObj, \p size is filled with the buffer - * size if not null. - * - * If the \p pyObj is a non-contiguous buffer a Python error is set. - */ - LIBSHIBOKEN_API void *getPointer(PyObject *pyObj, Py_ssize_t *size = nullptr); - -} // namespace Buffer -} // namespace Shiboken - -#endif diff --git a/sources/shiboken2/libshiboken/shibokenmacros.h b/sources/shiboken2/libshiboken/shibokenmacros.h deleted file mode 100644 index d8f45868a..000000000 --- a/sources/shiboken2/libshiboken/shibokenmacros.h +++ /dev/null @@ -1,64 +0,0 @@ -/**************************************************************************** -** -** Copyright (C) 2020 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$ -** -****************************************************************************/ - -#ifndef SHIBOKENMACROS_H -#define SHIBOKENMACROS_H - -// LIBSHIBOKEN_API macro is used for the public API symbols. -#if defined _WIN32 -# define LIBSHIBOKEN_EXPORT __declspec(dllexport) -# ifdef _MSC_VER -# define LIBSHIBOKEN_IMPORT __declspec(dllimport) -# else -# define LIBSHIBOKEN_IMPORT -# endif -# define SBK_DEPRECATED(func) __declspec(deprecated) func -#else -# define LIBSHIBOKEN_EXPORT __attribute__ ((visibility("default"))) -# define LIBSHIBOKEN_IMPORT -# define SBK_DEPRECATED(func) func __attribute__ ((deprecated)) -#endif - -#ifdef BUILD_LIBSHIBOKEN -# define LIBSHIBOKEN_API LIBSHIBOKEN_EXPORT -#else -# define LIBSHIBOKEN_API LIBSHIBOKEN_IMPORT -#endif - -#endif // SHIBOKENMACROS_H diff --git a/sources/shiboken2/libshiboken/signature.h b/sources/shiboken2/libshiboken/signature.h deleted file mode 100644 index b77cc0f4c..000000000 --- a/sources/shiboken2/libshiboken/signature.h +++ /dev/null @@ -1,55 +0,0 @@ -/**************************************************************************** -** -** Copyright (C) 2018 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$ -** -****************************************************************************/ - -#ifndef SIGNATURE_H -#define SIGNATURE_H - -extern "C" -{ - -LIBSHIBOKEN_API int InitSignatureStrings(PyTypeObject *, const char *[]); -LIBSHIBOKEN_API void FinishSignatureInitialization(PyObject *, const char *[]); -LIBSHIBOKEN_API void SetError_Argument(PyObject *, const char *); -LIBSHIBOKEN_API PyObject *Sbk_TypeGet___signature__(PyObject *, PyObject *); -LIBSHIBOKEN_API PyObject *Sbk_TypeGet___doc__(PyObject *); -LIBSHIBOKEN_API PyObject *GetFeatureDict(); - -} // extern "C" - -#endif // SIGNATURE_H diff --git a/sources/shiboken2/libshiboken/signature/signature.cpp b/sources/shiboken2/libshiboken/signature/signature.cpp deleted file mode 100644 index 085d751aa..000000000 --- a/sources/shiboken2/libshiboken/signature/signature.cpp +++ /dev/null @@ -1,482 +0,0 @@ -/**************************************************************************** -** -** Copyright (C) 2020 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$ -** -****************************************************************************/ - -//////////////////////////////////////////////////////////////////////////// -// -// signature.cpp -// ------------- -// -// This is the main file of the signature module. -// It contains the most important functions and avoids confusion -// by moving many helper functions elsewhere. -// -// General documentation can be found in `signature_doc.rst`. -// - -#include "basewrapper.h" -#include "autodecref.h" -#include "sbkstring.h" -#include "sbkstaticstrings.h" -#include "sbkstaticstrings_p.h" - -#include "signature_p.h" -#include <structmember.h> - -using namespace Shiboken; - -extern "C" -{ - -static PyObject *CreateSignature(PyObject *props, PyObject *key) -{ - /* - * Here is the new function to create all signatures. It simply calls - * into Python and creates a signature object directly. - * This is so much simpler than using all the attributes explicitly - * to support '_signature_is_functionlike()'. - */ - return PyObject_CallFunction(pyside_globals->create_signature_func, - const_cast<char *>("(OO)"), props, key); -} - -PyObject *GetClassOrModOf(PyObject *ob) -{ - /* - * Return the type or module of a function or type. - * The purpose is finally to use the name of the object. - */ - if (PyType_Check(ob)) { - // PySide-928: The type case must do refcounting like the others as well. - Py_INCREF(ob); - return ob; - } - if (PyType_IsSubtype(Py_TYPE(ob), &PyCFunction_Type)) - return _get_class_of_cf(ob); - if (Py_TYPE(ob) == PepStaticMethod_TypePtr) - return _get_class_of_sm(ob); - if (Py_TYPE(ob) == PepMethodDescr_TypePtr) - return _get_class_of_descr(ob); - if (Py_TYPE(ob) == &PyWrapperDescr_Type) - return _get_class_of_descr(ob); - Py_FatalError("unexpected type in GetClassOrModOf"); - return nullptr; -} - -PyObject *GetTypeKey(PyObject *ob) -{ - assert(PyType_Check(ob) || PyModule_Check(ob)); - /* - * Obtain a unique key using the module name and the type name. - * - * PYSIDE-1286: We use correct __module__ and __qualname__, now. - */ - AutoDecRef module_name(PyObject_GetAttr(ob, PyMagicName::module())); - if (module_name.isNull()) { - // We have no module_name because this is a module ;-) - PyErr_Clear(); - module_name.reset(PyObject_GetAttr(ob, PyMagicName::name())); - return Py_BuildValue("O", module_name.object()); - } - AutoDecRef class_name(_get_qualname(ob)); - if (class_name.isNull()) { - Py_FatalError("Signature: missing class name in GetTypeKey"); - return nullptr; - } - return Py_BuildValue("(OO)", module_name.object(), class_name.object()); -} - -static PyObject *empty_dict = nullptr; - -PyObject *TypeKey_to_PropsDict(PyObject *type_key, PyObject *obtype) -{ - PyObject *dict = PyDict_GetItem(pyside_globals->arg_dict, type_key); - if (dict == nullptr) { - if (empty_dict == nullptr) - empty_dict = PyDict_New(); - dict = empty_dict; - } - if (!PyDict_Check(dict)) - dict = PySide_BuildSignatureProps(type_key); - return dict; -} - -static PyObject *_GetSignature_Cached(PyObject *props, PyObject *func_kind, PyObject *modifier) -{ - // Special case: We want to know the func_kind. - if (modifier) { -#if PY_VERSION_HEX >= 0x03000000 - PyUnicode_InternInPlace(&modifier); -#else - PyString_InternInPlace(&modifier); -#endif - if (modifier == PyMagicName::func_kind()) - return Py_BuildValue("O", func_kind); - } - - AutoDecRef key(modifier == nullptr ? Py_BuildValue("O", func_kind) - : Py_BuildValue("(OO)", func_kind, modifier)); - PyObject *value = PyDict_GetItem(props, key); - if (value == nullptr) { - // we need to compute a signature object - value = CreateSignature(props, key); - if (value != nullptr) { - if (PyDict_SetItem(props, key, value) < 0) - // this is an error - return nullptr; - } - else { - // key not found - Py_RETURN_NONE; - } - } - return Py_INCREF(value), value; -} - -PyObject *GetSignature_Function(PyObject *obfunc, PyObject *modifier) -{ - // make sure that we look into PyCFunction, only... - if (Py_TYPE(obfunc) == PepFunction_TypePtr) - Py_RETURN_NONE; - AutoDecRef obtype_mod(GetClassOrModOf(obfunc)); - AutoDecRef type_key(GetTypeKey(obtype_mod)); - if (type_key.isNull()) - Py_RETURN_NONE; - PyObject *dict = TypeKey_to_PropsDict(type_key, obtype_mod); - if (dict == nullptr) - return nullptr; - AutoDecRef func_name(PyObject_GetAttr(obfunc, PyMagicName::name())); - PyObject *props = !func_name.isNull() ? PyDict_GetItem(dict, func_name) : nullptr; - if (props == nullptr) - Py_RETURN_NONE; - - int flags = PyCFunction_GET_FLAGS(obfunc); - PyObject *func_kind; - if (PyModule_Check(obtype_mod)) - func_kind = PyName::function(); - else if (flags & METH_CLASS) - func_kind = PyName::classmethod(); - else if (flags & METH_STATIC) - func_kind = PyName::staticmethod(); - else - func_kind = PyName::method(); - return _GetSignature_Cached(props, func_kind, modifier); -} - -PyObject *GetSignature_Wrapper(PyObject *ob, PyObject *modifier) -{ - AutoDecRef func_name(PyObject_GetAttr(ob, PyMagicName::name())); - AutoDecRef objclass(PyObject_GetAttr(ob, PyMagicName::objclass())); - AutoDecRef class_key(GetTypeKey(objclass)); - if (func_name.isNull() || objclass.isNull() || class_key.isNull()) - return nullptr; - PyObject *dict = TypeKey_to_PropsDict(class_key, objclass); - if (dict == nullptr) - return nullptr; - PyObject *props = PyDict_GetItem(dict, func_name); - if (props == nullptr) - Py_RETURN_NONE; - return _GetSignature_Cached(props, PyName::method(), modifier); -} - -PyObject *GetSignature_TypeMod(PyObject *ob, PyObject *modifier) -{ - AutoDecRef ob_name(PyObject_GetAttr(ob, PyMagicName::name())); - AutoDecRef ob_key(GetTypeKey(ob)); - - PyObject *dict = TypeKey_to_PropsDict(ob_key, ob); - if (dict == nullptr) - return nullptr; - PyObject *props = PyDict_GetItem(dict, ob_name); - if (props == nullptr) - Py_RETURN_NONE; - return _GetSignature_Cached(props, PyName::method(), modifier); -} - -//////////////////////////////////////////////////////////////////////////// -// -// get_signature -- providing a superior interface -// -// Additional to the interface via `__signature__`, we also provide -// a general function, which allows for different signature layouts. -// The `modifier` argument is a string that is passed in from `loader.py`. -// Configuration what the modifiers mean is completely in Python. -// - -PyObject *get_signature_intern(PyObject *ob, PyObject *modifier) -{ - if (PyType_IsSubtype(Py_TYPE(ob), &PyCFunction_Type)) - return pyside_cf_get___signature__(ob, modifier); - if (Py_TYPE(ob) == PepStaticMethod_TypePtr) - return pyside_sm_get___signature__(ob, modifier); - if (Py_TYPE(ob) == PepMethodDescr_TypePtr) - return pyside_md_get___signature__(ob, modifier); - if (PyType_Check(ob)) - return pyside_tp_get___signature__(ob, modifier); - if (Py_TYPE(ob) == &PyWrapperDescr_Type) - return pyside_wd_get___signature__(ob, modifier); - return nullptr; -} - -static PyObject *get_signature(PyObject * /* self */, PyObject *args) -{ - PyObject *ob; - PyObject *modifier = nullptr; - - init_module_1(); - - if (!PyArg_ParseTuple(args, "O|O", &ob, &modifier)) - return nullptr; - if (Py_TYPE(ob) == PepFunction_TypePtr) - Py_RETURN_NONE; - PyObject *ret = get_signature_intern(ob, modifier); - if (ret != nullptr) - return ret; - Py_RETURN_NONE; -} - -PyMethodDef signature_methods[] = { - {"get_signature", (PyCFunction)get_signature, METH_VARARGS, - "get the __signature__, but pass an optional string parameter"}, - {nullptr, nullptr} -}; - -//////////////////////////////////////////////////////////////////////////// -// -// Argument Handling -// ----------------- -// -// * PySide_BuildSignatureArgs -// -// Called during class or module initialization. -// The signature strings from the C modules are stored in a dict for -// later use. -// -// * PySide_BuildSignatureProps -// -// Called on demand during signature retieval. This function calls all the way -// through `parser.py` and prepares all properties for the functions of the class. -// The parsed properties can then be used to create signature objects. -// - -static int PySide_BuildSignatureArgs(PyObject *obtype_mod, const char *signatures[]) -{ - init_module_1(); - AutoDecRef type_key(GetTypeKey(obtype_mod)); - /* - * PYSIDE-996: Avoid string overflow in MSVC, which has a limit of - * 2**15 unicode characters (64 K memory). - * Instead of one huge string, we take a ssize_t that is the - * address of a string array. It will not be turned into a real - * string list until really used by Python. This is quite optimal. - */ - AutoDecRef numkey(Py_BuildValue("n", signatures)); - if (type_key.isNull() || numkey.isNull() - || PyDict_SetItem(pyside_globals->arg_dict, type_key, numkey) < 0) - return -1; - /* - * We record also a mapping from type key to type/module. This helps to - * lazily initialize the Py_LIMITED_API in name_key_to_func(). - */ - return PyDict_SetItem(pyside_globals->map_dict, type_key, obtype_mod) == 0 ? 0 : -1; -} - -PyObject *PySide_BuildSignatureProps(PyObject *type_key) -{ - /* - * Here is the second part of the function. - * This part will be called on-demand when needed by some attribute. - * We simply pick up the arguments that we stored here and replace - * them by the function result. - */ - init_module_2(); - if (type_key == nullptr) - return nullptr; - PyObject *numkey = PyDict_GetItem(pyside_globals->arg_dict, type_key); - AutoDecRef strings(_address_to_stringlist(numkey)); - if (strings.isNull()) - return nullptr; - AutoDecRef arg_tup(Py_BuildValue("(OO)", type_key, strings.object())); - if (arg_tup.isNull()) - return nullptr; - PyObject *dict = PyObject_CallObject(pyside_globals->pyside_type_init_func, arg_tup); - if (dict == nullptr) { - if (PyErr_Occurred()) - return nullptr; - // No error: return an empty dict. - if (empty_dict == nullptr) - empty_dict = PyDict_New(); - return empty_dict; - } - // PYSIDE-1019: Build snake case versions of the functions. - if (insert_snake_case_variants(dict) < 0) - return nullptr; - // We replace the arguments by the result dict. - if (PyDict_SetItem(pyside_globals->arg_dict, type_key, dict) < 0) - return nullptr; - return dict; -} -// -//////////////////////////////////////////////////////////////////////////// - -static int PySide_FinishSignatures(PyObject *module, const char *signatures[]) -{ - /* - * Initialization of module functions and resolving of static methods. - */ - const char *name = PyModule_GetName(module); - if (name == nullptr) - return -1; - - // we abuse the call for types, since they both have a __name__ attribute. - if (PySide_BuildSignatureArgs(module, signatures) < 0) - return -1; - - /* - * Note: This function crashed when called from PySide_BuildSignatureArgs. - * Probably this was an import timing problem. - * - * Pep384: We need to switch this always on since we have no access - * to the PyCFunction attributes. Therefore I simplified things - * and always use our own mapping. - */ - PyObject *key, *func, *obdict = PyModule_GetDict(module); - Py_ssize_t pos = 0; - - while (PyDict_Next(obdict, &pos, &key, &func)) - if (PyCFunction_Check(func)) - if (PyDict_SetItem(pyside_globals->map_dict, func, module) < 0) - return -1; - if (_finish_nested_classes(obdict) < 0) - return -1; - // The finish_import function will not work the first time since phase 2 - // was not yet run. But that is ok, because the first import is always for - // the shiboken module (or a test module). - if (pyside_globals->finish_import_func == nullptr) { - assert(strncmp(name, "PySide2.", 8) != 0); - return 0; - } - AutoDecRef ret(PyObject_CallFunction( - pyside_globals->finish_import_func, const_cast<char *>("(O)"), module)); - return ret.isNull() ? -1 : 0; -} - -//////////////////////////////////////////////////////////////////////////// -// -// External functions interface -// -// These are exactly the supported functions from `signature.h`. -// - -int InitSignatureStrings(PyTypeObject *type, const char *signatures[]) -{ - auto *ob_type = reinterpret_cast<PyObject *>(type); - int ret = PySide_BuildSignatureArgs(ob_type, signatures); - if (ret < 0) { - PyErr_Print(); - PyErr_SetNone(PyExc_ImportError); - } - return ret; -} - -void FinishSignatureInitialization(PyObject *module, const char *signatures[]) -{ - /* - * This function is called at the very end of a module initialization. - * We now patch certain types to support the __signature__ attribute, - * initialize module functions and resolve static methods. - * - * Still, it is not possible to call init phase 2 from here, - * because the import is still running. Do it from Python! - */ - if ( PySide_PatchTypes() < 0 - || PySide_FinishSignatures(module, signatures) < 0) { - PyErr_Print(); - PyErr_SetNone(PyExc_ImportError); - } -} - -void SetError_Argument(PyObject *args, const char *func_name) -{ - /* - * This function replaces the type error construction with extra - * overloads parameter in favor of using the signature module. - * Error messages are rare, so we do it completely in Python. - */ - init_module_1(); - init_module_2(); - AutoDecRef res(PyObject_CallFunction(pyside_globals->seterror_argument_func, - const_cast<char *>("(Os)"), args, func_name)); - if (res.isNull()) { - PyErr_Print(); - Py_FatalError("seterror_argument did not receive a result"); - } - PyObject *err, *msg; - if (!PyArg_UnpackTuple(res, func_name, 2, 2, &err, &msg)) { - PyErr_Print(); - Py_FatalError("unexpected failure in seterror_argument"); - } - PyErr_SetObject(err, msg); -} - -/* - * Support for the metatype SbkObjectType_Type's tp_getset. - * - * This was not necessary for __signature__, because PyType_Type inherited it. - * But the __doc__ attribute existed already by inheritance, and calling - * PyType_Modified() is not supported. So we added the getsets explicitly - * to the metatype. - */ - -PyObject *Sbk_TypeGet___signature__(PyObject *ob, PyObject *modifier) -{ - return pyside_tp_get___signature__(ob, modifier); -} - -PyObject *Sbk_TypeGet___doc__(PyObject *ob) -{ - return pyside_tp_get___doc__(ob); -} - -PyObject *GetFeatureDict() -{ - init_module_1(); - return pyside_globals->feature_dict; -} - -} //extern "C" diff --git a/sources/shiboken2/libshiboken/signature/signature_doc.rst b/sources/shiboken2/libshiboken/signature/signature_doc.rst deleted file mode 100644 index f3dc652b6..000000000 --- a/sources/shiboken2/libshiboken/signature/signature_doc.rst +++ /dev/null @@ -1,357 +0,0 @@ -************************* -The signature C extension -************************* - -This module is a C extension for CPython 3.5 and up, and CPython 2.7. -Its purpose is to provide support for the ``__signature__`` attribute -of builtin PyCFunction objects. - - -Short Introduction to the Topic -=============================== - -Beginning with CPython 3.5, Python functions began to grow a ``__signature__`` -attribute for normal Python functions. This is totally optional and just -a nice-to-have feature in Python. - -PySide, on the other hand, could use ``__signature__`` very much, because the -typing info for the 15000+ PySide functions is really missing, and it -would be nice to have this info directly available. - - -The Idea to Support Signatures -============================== - -We want to have an additional ``__signature__`` attribute in all PySide -methods, without changing lots of generated code. -Therefore, we did not change any of the existing data structures, -but supported the new attribute by a global dictionary. - -When the ``__signature__`` property is requested, a method is called that -does a lookup in the global dict. This is a flexible approach with little impact -to the rest of the project. It has very limited overhead compared to direct -attribute access, but for the need of a signature access from time to time, -this is an adequate compromise. - - -How this Code Works -------------------- - -Signatures are supported for regular Python functions, only. Creating signatures -for ``PyCFunction`` objects would require quite some extra effort in Python. - -Fortunately, we found this special *stealth* technique, that saves us most of the -needed effort: - -The basic idea is to create a dummy Python function with **varnames**, **defaults** -and **annotations** properties, and then to use the inspect -module to create a signature object. This object is returned as the computed -result of the ``__signature__`` attribute of the real ``PyCFunction`` object. - -There is one thing that really changes Python a bit: - -* We added the ``__signature__`` attribute to every function. - -That is a little change to Python that does not harm, but it saves us -tons of code, that was needed in the early versions of the module. - -The internal work is done in two steps: - -* All functions of a class get the *signature text* when the module is imported. - This is only a very small overhead added to the startup time. It is a single - string for each whole class. -* The actual signature object is created later, when the attribute is really - requested. Signatures are cached and only created on first access. - -Example: - -The ``PyCFunction`` ``QtWidgets.QApplication.palette`` is interrogated for its -signature. That means ``pyside_sm_get___signature__()`` is called. -It calls ``GetSignature_Function`` which returns the signature if it is found. - - -Why this Code is Fast ---------------------- - -It costs a little time (maybe 6 seconds) to run through every single signature -object, since these are more than 25000 Python objects. But all the signature -objects will be rarely accessed but in special applications. -The normal case are only a few accesses, and these are working pretty fast. - -The key to make this signature module fast is to avoid computation as much as -possible. When no signature objects are used, then almost no time is lost in -initialization. Only the above mentioned strings and some support modules are -additionally loaded on ``import PySide2``. -When it comes to signature usage, then late initialization is used and cached. -This technique is also known as *full laziness* in haskell. - -There are actually two locations where late initialization occurs: - -* ``dict`` can be no dict but a tuple. That is the initial argument tuple that - was saved by ``PySide_BuildSignatureArgs`` at module load time. - If so, then ``pyside_type_init`` in parser.py will be called, - which parses the string and creates the dict. -* ``props`` can be empty. Then ``create_signature`` in loader.py - is called, which uses a dummy function to produce a signature instance - with the inspect module. - -The initialization that is always done is just two dictionary writes -per class, and we have about 1000 classes. -To measure the additional overhead, we have simulated what happens -when ``from PySide2 import *`` is performed. -It turned out that the overhead is below 0.5 ms. - - -The Signature Package Structure -------------------------------- - -The C++ code involved with the signature module is completely in the file -shiboken2/libshiboken/signature.cpp . All other functionality is implemented in -the ``signature`` Python package. It has the following structure:: - - shiboken2/files.dir/shibokensupport/ - backport_inspect.py - - signature/ - loader.py - parser.py - mapping.py - errorhandler.py - layout.py - - lib/ - enum_sig.py - tool.py - - - -Really important are the **parser**, **mapping**, **errorhandler**, **enum_sig**, -**layout** and **loader** modules. The rest is needed to create Python 2 compatibility -or be compatible with embedding and installers. - - -loader.py -~~~~~~~~~ - -This module assembles and imports the ``inspect`` module, and then exports the -``create_signature`` function. This function takes a fake function and some -attributes and builds a ``__signature__`` object with the inspect module. - - -parser.py -~~~~~~~~~ - -This module takes a class signatures string from C++ and parses it into the -needed properties for the ``create_signature`` function. Its entry point is the -``pyside_type_init`` function, which is called from the C module via ``loader.py``. - - -mapping.py -~~~~~~~~~~ - -The purpose of the mapping module is maintaining a list of replacement strings -that map from the *signature text* in C to the property strings that Python -needs. A lot of mappings are resolved by rather complex expressions in ``parser.py``, -but a few hundred cases are better to spell explicitly, here. - - -errorhandler.py -~~~~~~~~~~~~~~~ - -Since ``Qt For Python 5.12``, we no longer use the builtin type error messages from C++. -Instead, we get much better results with the signature module. At the same time, -this enforced supporting shiboken as well, and the signature module was no longer -optional. - - -enum_sig.py -~~~~~~~~~~~ - -The diverse applications of the signature module all needed to iterate over modules, -classes and functions. In order to centralize this enumeration, the process has -been factored out as a context manager. The user has only to supply functions -that do the actual formatting. - -See for example the .pyi generator ``pyside2/PySide2/support/generate_pyi.py``. - - -layout.py -~~~~~~~~~ - -As more applications used the signature module, different formatting of signatures -was needed. To support that, we created the function ``create_signature``, which -has a parameter to choose from some prefefined layouts. - - -*typing27.py* -~~~~~~~~~~~~~ - -Python 2 has no typing module at all. This is a backport of the minimum that is needed. - - -*backport_inspect.py* -~~~~~~~~~~~~~~~~~~~~~ - -Python 2 has an inspect module, but lacks the signature functions, completely. -This module adds the missing functionality, which is merged at runtime into -the inspect module. - - -Multiple Arities ----------------- - -One aspect that was ignored so far was *multiple arities*: How to handle it when -a function has more than one signature? - -I did not find any note on how multiple signatures should be treated in Python, -but this simple rules seem to work well: - -* If there is a list, then it is a multi-signature. -* Otherwise, it is a simple signature. - - -Impacts of The Signature Module -=============================== - -The signature module has a number of impacts to other PySide modules, which were -created as a consequence of its existence, and there will be a few more in the -future: - - -existence_test.py ------------------ - -The file ``pyside2/tests/registry/existence_test.py`` was written using the -signatures from the signatures module. The idea is that there are some 15000 -functions with a certain signature. - -These functions should not get lost by some bad check-in. Therefore, a list -of all existing signatures is kept as a module that assembles a -dictionary. The function existence is checked, and also the exact arity. - -This module exists for every PySide release and every platform. The initial -module is generated once and saved as ``exists_{plat}_{version}.py``. - -An error is normally only reported as a warning, but: - - -Interaction With The Coin Module -~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ - -When this test program is run in COIN, then the warnings are turned into -errors. The reason is that only in COIN, we have a stable configuration -of PySide modules that can reliably be compared. - -These modules have the name ``exists_{platf}_{version}_ci.py``, and as a big -exception for generated code, these files are *intentionally* checked in. - - -What Happens When a List is Missing? -~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ - -When a new version of PySide gets created, then the existence test files -initially do not exist. - -When a COIN test is run, then it will complain about the error and create -the missing module on standard output. -But since COIN tests are run multiple times, the output that was generated -by the first test will still exist at the subsequent runs. -(If COIN was properly implemented, we could not take that advantage and -would need to implement that as an extra exception.) - -As a result, a missing module will be reported as a test which partially -succeeded (called "FLAKY"). To avoid further flaky tests and to activate as a real test, -we can now capture the error output of COIN and check the generated module -in. - - -Explicitly Enforcing Recreation -~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ - -The former way to regenerate the registry files was to remove the files -and check that in. This has the desired effect, but creates huge deltas. -As a more efficient way, we have prepared a comment in the first line -that contains the word "recreate". -By uncommenting this line, a NameError is triggered, which has the same -effect. - - -init_platform.py -~~~~~~~~~~~~~~~~ - -For generating the ``exists_{platf}_{version}`` modules, the module -``pyside2/tests/registry/init_platform.py`` was written. It can be used -standalone from the commandline, to check the compatibility of some -changes, directly. - - -scrape_testresults.py ---------------------- - -To simplify and automate the process of extracting the ``exists_{platf}_{version}_ci.py`` -files, the script ``pyside2/tests/registry/scrape_testresults.py`` has been written. - -This script scans the whole testresults website for PySide, that is:: - - https://testresults.qt.io/coin/api/results/pyside/pyside-setup/ - -On the first scan, the script runs less than 30 minutes. After that, a cache -is generated and the scan works *much* faster. The test results are placed -into the folder ``pyside2/tests/registry/testresults/embedded/`` with a -unique name that allows for easy sorting. Example:: - - testresults/embedded/2018_09_10_10_40_34-test_1536891759-exists_linux_5_11_2_ci.py - -These files are created only once. If they already exist, they are not touched, again. -The file `pyside2/tests/registry/known_urls.json`` holds all scanned URLs after -a successful scan. The ``testresults/embedded`` folder can be kept for reference -or can be removed. Important is only the json file. - -The result of a scan is then directly placed into the ``pyside2/tests/registry/`` -folder. It should be reviewed and then eventually checked in. - - -generate_pyi.py ---------------- - -``pyside2/PySide2/support/generate_pyi.py`` is still under development. -This module generates so-called hinting stubs for integration of PySide -with diverse *Python IDEs*. - -Although this module creates the stubs as an add-on, the -impact on the quality of the signature module is considerable: - -The module must create syntactically correct ``.pyi`` files which contain -not only signatures but also constants and enums of all PySide modules. -This serves as an extra challenge that has a very positive effect on -the completeness and correctness of signatures. - - -Current Extensions ------------------- - -Before the signature module was written, there already existed the concept of -signatures, but in a more C++ - centric way. From that time, there existed -the error messages, which are created when a function gets wrong argument types. - -These error messages were replaced by text generated on demand by -the signature module, in order to be more consistent and correct. -This was implemented in ``Qt For Python 5.12.0``. - -Additionally, the ``__doc__`` attribute of PySide methods was not set. -It was easy to get a nice ``help()`` feature by creating signatures -as default content for docstrings. -This was implemented in ``Qt For Python 5.12.1``. - - -Literature -========== - - `PEP 362 – Function Signature Object <https://www.python.org/dev/peps/pep-0362/>`__ - - `PEP 484 – Type Hints <https://www.python.org/dev/peps/pep-0484/>`__ - - `PEP 3107 – Function Annotations <https://www.python.org/dev/peps/pep-3107/>`__ - - -*Personal Remark: This module is dedicated to our lovebird "Püppi", who died on 2017-09-15.* diff --git a/sources/shiboken2/libshiboken/signature/signature_extend.cpp b/sources/shiboken2/libshiboken/signature/signature_extend.cpp deleted file mode 100644 index 1490a6003..000000000 --- a/sources/shiboken2/libshiboken/signature/signature_extend.cpp +++ /dev/null @@ -1,294 +0,0 @@ -/**************************************************************************** -** -** Copyright (C) 2020 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$ -** -****************************************************************************/ - -//////////////////////////////////////////////////////////////////////////// -// -// signature_extend.cpp -// -------------------- -// -// This file contains the additions and changes to the following -// Python types: -// -// PyMethodDescr_Type -// PyCFunction_Type -// PyStaticMethod_Type -// PyType_Type -// PyWrapperDescr_Type -// -// Their `tp_getset` fields are modified so support the `__signature__` -// attribute and additions to the `__doc__` attribute. -// - -#include "autodecref.h" -#include "sbkstring.h" -#include "sbkstaticstrings.h" -#include "sbkstaticstrings_p.h" - -#include "signature_p.h" - -using namespace Shiboken; - -extern "C" { - -typedef PyObject *(*signaturefunc)(PyObject *, PyObject *); - -static PyObject *_get_written_signature(signaturefunc sf, PyObject *ob, PyObject *modifier) -{ - /* - * Be a writable Attribute, but have a computed value. - * - * If a signature has not been written, call the signature function. - * If it has been written, return the written value. - * After __del__ was called, the function value re-appears. - * - * Note: This serves also for the new version that does not allow any - * assignment if we have a computed value. We only need to check if - * a computed value exists and then forbid writing. - * See pyside_set___signature - */ - PyObject *ret = PyDict_GetItem(pyside_globals->value_dict, ob); - if (ret == nullptr) - return ob == nullptr ? nullptr : sf(ob, modifier); - Py_INCREF(ret); - return ret; -} - -PyObject *pyside_cf_get___signature__(PyObject *func, PyObject *modifier) -{ - init_module_2(); - return _get_written_signature(GetSignature_Function, func, modifier); -} - -PyObject *pyside_sm_get___signature__(PyObject *sm, PyObject *modifier) -{ - init_module_2(); - AutoDecRef func(PyObject_GetAttr(sm, PyMagicName::func())); - if (Py_TYPE(func) == PepFunction_TypePtr) - return PyObject_GetAttr(func, PyMagicName::signature()); - return _get_written_signature(GetSignature_Function, func, modifier); -} - -PyObject *pyside_md_get___signature__(PyObject *ob_md, PyObject *modifier) -{ - init_module_2(); - AutoDecRef func(name_key_to_func(ob_md)); - if (func.object() == Py_None) - return Py_None; - if (func.isNull()) - Py_FatalError("missing mapping in MethodDescriptor"); - return pyside_cf_get___signature__(func, modifier); -} - -PyObject *pyside_wd_get___signature__(PyObject *ob, PyObject *modifier) -{ - init_module_2(); - return _get_written_signature(GetSignature_Wrapper, ob, modifier); -} - -PyObject *pyside_tp_get___signature__(PyObject *obtype_mod, PyObject *modifier) -{ - init_module_2(); - return _get_written_signature(GetSignature_TypeMod, obtype_mod, modifier); -} - -//////////////////////////////////////////////////////////////////////////// -// -// Augmenting builtin types with a __signature__ attribute. -// -// This is a harmless change to Python, similar like __text_signature__. -// We could avoid it, but then we would need to copy quite some module -// initialization functions which are pretty version- and word size -// dependent. I think this little patch is the lesser of the two evils. -// -// Please note that in fact we are modifying 'type', the metaclass of all -// objects, because we add new functionality. -// -// Addendum 2019-01-12: We now also compute a docstring from the signature. -// - -// keep the original __doc__ functions -static PyObject *old_cf_doc_descr = nullptr; -static PyObject *old_sm_doc_descr = nullptr; -static PyObject *old_md_doc_descr = nullptr; -static PyObject *old_tp_doc_descr = nullptr; -static PyObject *old_wd_doc_descr = nullptr; - -static int handle_doc_in_progress = 0; - -static PyObject *handle_doc(PyObject *ob, PyObject *old_descr) -{ - init_module_1(); - init_module_2(); - AutoDecRef ob_type_mod(GetClassOrModOf(ob)); - const char *name; - if (PyModule_Check(ob_type_mod)) - name = PyModule_GetName(ob_type_mod); - else - name = reinterpret_cast<PyTypeObject *>(ob_type_mod.object())->tp_name; - if (handle_doc_in_progress || name == nullptr - || strncmp(name, "PySide2.", 8) != 0) - return PyObject_CallMethodObjArgs(old_descr, - PyMagicName::get(), - ob, nullptr); - handle_doc_in_progress++; - PyObject *res = PyObject_CallFunction( - pyside_globals->make_helptext_func, - const_cast<char *>("(O)"), ob); - handle_doc_in_progress--; - if (res == nullptr) { - PyErr_Print(); - Py_FatalError("handle_doc did not receive a result"); - } - return res; -} - -static PyObject *pyside_cf_get___doc__(PyObject *cf) -{ - return handle_doc(cf, old_cf_doc_descr); -} - -static PyObject *pyside_sm_get___doc__(PyObject *sm) -{ - return handle_doc(sm, old_sm_doc_descr); -} - -static PyObject *pyside_md_get___doc__(PyObject *md) -{ - return handle_doc(md, old_md_doc_descr); -} - -PyObject *pyside_tp_get___doc__(PyObject *tp) -{ - return handle_doc(tp, old_tp_doc_descr); -} - -static PyObject *pyside_wd_get___doc__(PyObject *wd) -{ - return handle_doc(wd, old_wd_doc_descr); -} - -// the default setter for all objects -static int pyside_set___signature__(PyObject *op, PyObject *value) -{ - // By this additional check, this function refuses write access. - // We consider both nullptr and Py_None as not been written. - AutoDecRef has_val(get_signature_intern(op, nullptr)); - if (!(has_val.isNull() || has_val == Py_None)) { - PyErr_Format(PyExc_AttributeError, - "Attribute '__signature__' of '%.50s' object is not writable", - Py_TYPE(op)->tp_name); - return -1; - } - int ret = value == nullptr ? PyDict_DelItem(pyside_globals->value_dict, op) - : PyDict_SetItem(pyside_globals->value_dict, op, value); - Py_XINCREF(value); - return ret; -} - -static PyGetSetDef new_PyCFunction_getsets[] = { - {const_cast<char *>("__doc__"), (getter)pyside_cf_get___doc__}, - {const_cast<char *>("__signature__"), (getter)pyside_cf_get___signature__, - (setter)pyside_set___signature__}, - {nullptr} -}; - -static PyGetSetDef new_PyStaticMethod_getsets[] = { - {const_cast<char *>("__doc__"), (getter)pyside_sm_get___doc__}, - {const_cast<char *>("__signature__"), (getter)pyside_sm_get___signature__, - (setter)pyside_set___signature__}, - {nullptr} -}; - -static PyGetSetDef new_PyMethodDescr_getsets[] = { - {const_cast<char *>("__doc__"), (getter)pyside_md_get___doc__}, - {const_cast<char *>("__signature__"), (getter)pyside_md_get___signature__, - (setter)pyside_set___signature__}, - {nullptr} -}; - -static PyGetSetDef new_PyType_getsets[] = { - {const_cast<char *>("__doc__"), (getter)pyside_tp_get___doc__}, - {const_cast<char *>("__signature__"), (getter)pyside_tp_get___signature__, - (setter)pyside_set___signature__}, - {nullptr} -}; - -static PyGetSetDef new_PyWrapperDescr_getsets[] = { - {const_cast<char *>("__doc__"), (getter)pyside_wd_get___doc__}, - {const_cast<char *>("__signature__"), (getter)pyside_wd_get___signature__, - (setter)pyside_set___signature__}, - {nullptr} -}; - -int PySide_PatchTypes(void) -{ - static int init_done = 0; - - if (!init_done) { - AutoDecRef meth_descr(PyObject_GetAttrString( - reinterpret_cast<PyObject *>(&PyString_Type), "split")); - AutoDecRef wrap_descr(PyObject_GetAttrString( - reinterpret_cast<PyObject *>(Py_TYPE(Py_True)), "__add__")); - // abbreviations for readability - auto md_gs = new_PyMethodDescr_getsets; - auto md_doc = &old_md_doc_descr; - auto cf_gs = new_PyCFunction_getsets; - auto cf_doc = &old_cf_doc_descr; - auto sm_gs = new_PyStaticMethod_getsets; - auto sm_doc = &old_sm_doc_descr; - auto tp_gs = new_PyType_getsets; - auto tp_doc = &old_tp_doc_descr; - auto wd_gs = new_PyWrapperDescr_getsets; - auto wd_doc = &old_wd_doc_descr; - - if (meth_descr.isNull() || wrap_descr.isNull() - || PyType_Ready(Py_TYPE(meth_descr)) < 0 - || add_more_getsets(PepMethodDescr_TypePtr, md_gs, md_doc) < 0 - || add_more_getsets(&PyCFunction_Type, cf_gs, cf_doc) < 0 - || add_more_getsets(PepStaticMethod_TypePtr, sm_gs, sm_doc) < 0 - || add_more_getsets(&PyType_Type, tp_gs, tp_doc) < 0 - || add_more_getsets(Py_TYPE(wrap_descr), wd_gs, wd_doc) < 0 - ) - return -1; - init_done = 1; - } - return 0; -} - -} // extern "C" diff --git a/sources/shiboken2/libshiboken/signature/signature_globals.cpp b/sources/shiboken2/libshiboken/signature/signature_globals.cpp deleted file mode 100644 index 6af64682e..000000000 --- a/sources/shiboken2/libshiboken/signature/signature_globals.cpp +++ /dev/null @@ -1,295 +0,0 @@ -/**************************************************************************** -** -** Copyright (C) 2020 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$ -** -****************************************************************************/ - -//////////////////////////////////////////////////////////////////////////// -// -// signature_global.cpp -// -// This file contains the global data structures and init code. -// - -#include "autodecref.h" -#include "sbkstring.h" -#include "sbkstaticstrings.h" -#include "sbkstaticstrings_p.h" - -#include "signature_p.h" - -using namespace Shiboken; - -extern "C" { - -static const char *PySide_CompressedSignaturePackage[] = { -#include "embed/signature_inc.h" - }; - -static const unsigned char PySide_SignatureLoader[] = { -#include "embed/signature_bootstrap_inc.h" - }; - -static PyObject *_init_pyside_extension(PyObject * /* self */, PyObject * /* args */) -{ - init_module_1(); - init_module_2(); - Py_RETURN_NONE; -} - -// This function will be inserted into __builtins__. -static PyMethodDef init_methods[] = { - {"_init_pyside_extension", (PyCFunction)_init_pyside_extension, METH_NOARGS}, - {nullptr, nullptr} -}; - -static safe_globals_struc *init_phase_1(PyMethodDef *init_meth) -{ - { - auto *p = reinterpret_cast<safe_globals_struc *> - (malloc(sizeof(safe_globals_struc))); - if (p == nullptr) - goto error; - /* - * Initializing module signature_bootstrap. - * Since we now have an embedding script, we can do this without any - * Python strings in the C code. - */ -#ifdef Py_LIMITED_API - // We must work for multiple versions, so use source code. -#else - AutoDecRef marshal_module(PyImport_Import(PyName::marshal())); - if (marshal_module.isNull()) - goto error; - AutoDecRef loads(PyObject_GetAttr(marshal_module, PyName::loads())); - if (loads.isNull()) - goto error; -#endif - char *bytes_cast = reinterpret_cast<char *>( - const_cast<unsigned char *>(PySide_SignatureLoader)); - AutoDecRef bytes(PyBytes_FromStringAndSize(bytes_cast, sizeof(PySide_SignatureLoader))); - if (bytes.isNull()) - goto error; -#ifdef Py_LIMITED_API - PyObject *builtins = PyEval_GetBuiltins(); - PyObject *compile = PyDict_GetItem(builtins, PyName::compile()); - if (compile == nullptr) - goto error; - AutoDecRef code_obj(PyObject_CallFunction(compile, "Oss", - bytes.object(), "(builtin)", "exec")); -#else - AutoDecRef code_obj(PyObject_CallFunctionObjArgs( - loads, bytes.object(), nullptr)); -#endif - if (code_obj.isNull()) - goto error; - p->helper_module = PyImport_ExecCodeModule(const_cast<char *> - ("signature_bootstrap"), code_obj); - if (p->helper_module == nullptr) - goto error; - // Initialize the module - PyObject *mdict = PyModule_GetDict(p->helper_module); - if (PyDict_SetItem(mdict, PyMagicName::builtins(), PyEval_GetBuiltins()) < 0) - goto error; - /* - * Unpack an embedded ZIP file with more signature modules. - * They will be loaded later with the zipimporter. - * Due to MSVC's limitation to 64k strings, we need to assemble pieces. - */ - const char **block_ptr = (const char **)PySide_CompressedSignaturePackage; - int npieces = 0; - PyObject *piece, *zipped_string_sequence = PyList_New(0); - if (zipped_string_sequence == nullptr) - return nullptr; - for (; **block_ptr != 0; ++block_ptr) { - npieces++; - // we avoid the string/unicode dilemma by not using PyString_XXX: - piece = Py_BuildValue("s", *block_ptr); - if (piece == nullptr || PyList_Append(zipped_string_sequence, piece) < 0) - goto error; - } - if (PyDict_SetItemString(mdict, "zipstring_sequence", zipped_string_sequence) < 0) - goto error; - Py_DECREF(zipped_string_sequence); - - // build a dict for diverse mappings - p->map_dict = PyDict_New(); - if (p->map_dict == nullptr) - goto error; - - // build a dict for the prepared arguments - p->arg_dict = PyDict_New(); - if (p->arg_dict == nullptr - || PyObject_SetAttrString(p->helper_module, "pyside_arg_dict", p->arg_dict) < 0) - goto error; - - // build a dict for assigned signature values - p->value_dict = PyDict_New(); - if (p->value_dict == nullptr) - goto error; - - // PYSIDE-1019: build a __feature__ dict - p->feature_dict = PyDict_New(); - if (p->feature_dict == nullptr - || PyObject_SetAttrString(p->helper_module, "pyside_feature_dict", p->feature_dict) < 0) - goto error; - - // This function will be disabled until phase 2 is done. - p->finish_import_func = nullptr; - - // Initialize the explicit init function. - AutoDecRef init(PyCFunction_NewEx(init_meth, nullptr, nullptr)); - if (init.isNull() - || PyDict_SetItemString(PyEval_GetBuiltins(), init_meth->ml_name, init) != 0) - goto error; - - return p; - } -error: - PyErr_Print(); - Py_FatalError("could not initialize part 1"); - return nullptr; -} - -static int init_phase_2(safe_globals_struc *p, PyMethodDef *methods) -{ - { - PyMethodDef *ml; - - // The single function to be called, but maybe more to come. - for (ml = methods; ml->ml_name != nullptr; ml++) { - PyObject *v = PyCFunction_NewEx(ml, nullptr, nullptr); - if (v == nullptr - || PyObject_SetAttrString(p->helper_module, ml->ml_name, v) != 0) - goto error; - Py_DECREF(v); - } - PyObject *bootstrap_func = PyObject_GetAttrString(p->helper_module, "bootstrap"); - if (bootstrap_func == nullptr) - goto error; - // The return value of the bootstrap function is the loader module. - PyObject *loader = PyObject_CallFunction(bootstrap_func, const_cast<char *>("()")); - if (loader == nullptr) - goto error; - // now the loader should be initialized - p->pyside_type_init_func = PyObject_GetAttrString(loader, "pyside_type_init"); - if (p->pyside_type_init_func == nullptr) - goto error; - p->create_signature_func = PyObject_GetAttrString(loader, "create_signature"); - if (p->create_signature_func == nullptr) - goto error; - p->seterror_argument_func = PyObject_GetAttrString(loader, "seterror_argument"); - if (p->seterror_argument_func == nullptr) - goto error; - p->make_helptext_func = PyObject_GetAttrString(loader, "make_helptext"); - if (p->make_helptext_func == nullptr) - goto error; - p->finish_import_func = PyObject_GetAttrString(loader, "finish_import"); - if (p->finish_import_func == nullptr) - goto error; - return 0; - } -error: - PyErr_Print(); - Py_FatalError("could not initialize part 2"); - return -1; -} - -#ifndef _WIN32 -//////////////////////////////////////////////////////////////////////////// -// a stack trace for linux-like platforms -#include <stdio.h> -#if defined(__GLIBC__) -# include <execinfo.h> -#endif -#include <signal.h> -#include <stdlib.h> -#include <unistd.h> - -static void handler(int sig) { -#if defined(__GLIBC__) - void *array[30]; - size_t size; - - // get void *'s for all entries on the stack - size = backtrace(array, 30); - - // print out all the frames to stderr -#endif - fprintf(stderr, "Error: signal %d:\n", sig); -#if defined(__GLIBC__) - backtrace_symbols_fd(array, size, STDERR_FILENO); -#endif - exit(1); -} - -//////////////////////////////////////////////////////////////////////////// -#endif // _WIN32 - -safe_globals pyside_globals = nullptr; - -void init_module_1(void) -{ - static int init_done = 0; - - if (!init_done) { - pyside_globals = init_phase_1(init_methods); - if (pyside_globals != nullptr) - init_done = 1; - -#ifndef _WIN32 - // We enable the stack trace in CI, only. - const char *testEnv = getenv("QTEST_ENVIRONMENT"); - if (testEnv && strstr(testEnv, "ci")) - signal(SIGSEGV, handler); // install our handler -#endif // _WIN32 - - } -} - -void init_module_2(void) -{ - static int init_done = 0; - - if (!init_done) { - // Phase 2 will call __init__.py which touches a signature, itself. - // Therefore we set init_done prior to init_phase_2(). - init_done = 1; - init_phase_2(pyside_globals, signature_methods); - } -} - -} // extern "C" diff --git a/sources/shiboken2/libshiboken/signature/signature_helper.cpp b/sources/shiboken2/libshiboken/signature/signature_helper.cpp deleted file mode 100644 index 2b360c786..000000000 --- a/sources/shiboken2/libshiboken/signature/signature_helper.cpp +++ /dev/null @@ -1,437 +0,0 @@ -/**************************************************************************** -** -** Copyright (C) 2020 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$ -** -****************************************************************************/ - -//////////////////////////////////////////////////////////////////////////// -// -// signature_helper.cpp -// -------------------- -// -// This file contains assoerted helper functions that are needed, -// but it is not helpful to see them all the time. -// - -#include "autodecref.h" -#include "sbkstring.h" -#include "sbkstaticstrings.h" -#include "sbkstaticstrings_p.h" - -#include "signature_p.h" - -using namespace Shiboken; - -extern "C" { - -// Helper for __qualname__ which might not always exist in Python 2 (type). -PyObject *_get_qualname(PyObject *ob) -{ - // We support __qualname__ for types, only. - assert(PyType_Check(ob)); - PyObject *name = PyObject_GetAttr(ob, PyMagicName::qualname()); - if (name == nullptr) { - PyErr_Clear(); - name = PyObject_GetAttr(ob, PyMagicName::name()); - } - return name; -} - -static int _fixup_getset(PyTypeObject *type, const char *name, PyGetSetDef *new_gsp) -{ - /* - * This function pre-fills all fields of the new gsp. We then - * insert the changed values. - */ - PyGetSetDef *gsp = type->tp_getset; - if (gsp != nullptr) { - for (; gsp->name != nullptr; gsp++) { - if (strcmp(gsp->name, name) == 0) { - new_gsp->set = gsp->set; - new_gsp->doc = gsp->doc; - new_gsp->closure = gsp->closure; - return 1; // success - } - } - } - PyMemberDef *md = type->tp_members; - if (md != nullptr) - for (; md->name != nullptr; md++) - if (strcmp(md->name, name) == 0) - return 1; - // staticmethod has just a `__doc__` in the class - assert(strcmp(type->tp_name, "staticmethod") == 0 && strcmp(name, "__doc__") == 0); - return 0; -} - -int add_more_getsets(PyTypeObject *type, PyGetSetDef *gsp, PyObject **doc_descr) -{ - /* - * This function is used to assign a new `__signature__` attribute, - * and also to override a `__doc__` or `__name__` attribute. - */ - assert(PyType_Check(type)); - PyType_Ready(type); - PyObject *dict = type->tp_dict; - for (; gsp->name != nullptr; gsp++) { - PyObject *have_descr = PyDict_GetItemString(dict, gsp->name); - if (have_descr != nullptr) { - Py_INCREF(have_descr); - if (strcmp(gsp->name, "__doc__") == 0) - *doc_descr = have_descr; - else - assert(false); - if (!_fixup_getset(type, gsp->name, gsp)) - continue; - } - AutoDecRef descr(PyDescr_NewGetSet(type, gsp)); - if (descr.isNull()) - return -1; - if (PyDict_SetItemString(dict, gsp->name, descr) < 0) - return -1; - } - PyType_Modified(type); - return 0; -} - -static PyObject *get_funcname(PyObject *ob) -{ - PyObject *func = ob; - if (Py_TYPE(ob) == PepStaticMethod_TypePtr) - func = PyObject_GetAttr(ob, PyMagicName::func()); - else - Py_INCREF(func); - PyObject *func_name = PyObject_GetAttr(func, PyMagicName::name()); - Py_DECREF(func); - if (func_name == nullptr) - Py_FatalError("unexpected name problem in compute_name_key"); - return func_name; -} - -static PyObject *compute_name_key(PyObject *ob) -{ - if (PyType_Check(ob)) - return GetTypeKey(ob); - AutoDecRef func_name(get_funcname(ob)); - AutoDecRef type_key(GetTypeKey(GetClassOrModOf(ob))); - return Py_BuildValue("(OO)", type_key.object(), func_name.object()); -} - -static PyObject *_func_with_new_name(PyTypeObject *type, - PyMethodDef *meth, - const char *new_name) -{ - /* - * Create a function with a lower case name. - * Note: This is similar to feature_select's methodWithNewName, - * but does not create a descriptor. - * XXX Maybe we can get rid of this, completely? - */ - auto obtype = reinterpret_cast<PyObject *>(type); - int len = strlen(new_name); - auto name = new char[len + 1]; - strcpy(name, new_name); - auto new_meth = new PyMethodDef; - new_meth->ml_name = name; - new_meth->ml_meth = meth->ml_meth; - new_meth->ml_flags = meth->ml_flags; - new_meth->ml_doc = meth->ml_doc; - return PyCFunction_NewEx(new_meth, obtype, nullptr); -} - -static int build_name_key_to_func(PyObject *obtype) -{ - auto *type = reinterpret_cast<PyTypeObject *>(obtype); - PyMethodDef *meth = type->tp_methods; - - if (meth == nullptr) - return 0; - - AutoDecRef type_key(GetTypeKey(obtype)); - for (; meth->ml_name != nullptr; meth++) { - AutoDecRef func(PyCFunction_NewEx(meth, obtype, nullptr)); - AutoDecRef func_name(get_funcname(func)); - AutoDecRef name_key(Py_BuildValue("(OO)", type_key.object(), func_name.object())); - if (func.isNull() || name_key.isNull() - || PyDict_SetItem(pyside_globals->map_dict, name_key, func) < 0) - return -1; - } - // PYSIDE-1019: Now we repeat the same for snake case names. - meth = type->tp_methods; - for (; meth->ml_name != nullptr; meth++) { - const char *name = String::toCString(String::getSnakeCaseName(meth->ml_name, true)); - AutoDecRef func(_func_with_new_name(type, meth, name)); - AutoDecRef func_name(get_funcname(func)); - AutoDecRef name_key(Py_BuildValue("(OO)", type_key.object(), func_name.object())); - if (func.isNull() || name_key.isNull() - || PyDict_SetItem(pyside_globals->map_dict, name_key, func) < 0) - return -1; - } - return 0; -} - -PyObject *name_key_to_func(PyObject *ob) -{ - /* - * We build a mapping from name_key to function. - * This could also be computed directly, but the Limited API - * makes this impossible. So we always build our own mapping. - */ - AutoDecRef name_key(compute_name_key(ob)); - if (name_key.isNull()) - Py_RETURN_NONE; - - PyObject *ret = PyDict_GetItem(pyside_globals->map_dict, name_key); - if (ret == nullptr) { - // do a lazy initialization - AutoDecRef type_key(GetTypeKey(GetClassOrModOf(ob))); - PyObject *type = PyDict_GetItem(pyside_globals->map_dict, - type_key); - if (type == nullptr) - Py_RETURN_NONE; - assert(PyType_Check(type)); - if (build_name_key_to_func(type) < 0) - return nullptr; - ret = PyDict_GetItem(pyside_globals->map_dict, name_key); - } - Py_XINCREF(ret); - return ret; -} - -static PyObject *_build_new_entry(PyObject *new_name, PyObject *value) -{ - PyObject *new_value = PyDict_Copy(value); - PyObject *multi = PyDict_GetItem(value, PyName::multi()); - if (multi != nullptr && Py_TYPE(multi) == &PyList_Type) { - ssize_t len = PyList_Size(multi); - AutoDecRef list(PyList_New(len)); - if (list.isNull()) - return nullptr; - for (int idx = 0; idx < len; ++idx) { - auto multi_entry = PyList_GetItem(multi, idx); - auto dup = PyDict_Copy(multi_entry); - if (PyDict_SetItem(dup, PyName::name(), new_name) < 0) - return nullptr; - if (PyList_SetItem(list, idx, dup) < 0) - return nullptr; - } - if (PyDict_SetItem(new_value, PyName::multi(), list) < 0) - return nullptr; - } else { - if (PyDict_SetItem(new_value, PyName::name(), new_name) < 0) - return nullptr; - } - return new_value; -} - -int insert_snake_case_variants(PyObject *dict) -{ - AutoDecRef snake_dict(PyDict_New()); - PyObject *key, *value; - Py_ssize_t pos = 0; - while (PyDict_Next(dict, &pos, &key, &value)) { - AutoDecRef name(String::getSnakeCaseName(key, true)); - AutoDecRef new_value(_build_new_entry(name, value)); - if (PyDict_SetItem(snake_dict, name, new_value) < 0) - return -1; - } - return PyDict_Merge(dict, snake_dict, 0); -} - -PyObject *_get_class_of_cf(PyObject *ob_cf) -{ - PyObject *selftype = PyCFunction_GET_SELF(ob_cf); - if (selftype == nullptr) { - selftype = PyDict_GetItem(pyside_globals->map_dict, ob_cf); - if (selftype == nullptr) { - // This must be an overloaded function that we handled special. - AutoDecRef special(Py_BuildValue("(OO)", ob_cf, PyName::overload())); - selftype = PyDict_GetItem(pyside_globals->map_dict, special); - if (selftype == nullptr) { - // This is probably a module function. We will return type(None). - selftype = Py_None; - } - } - } - - PyObject *obtype_mod = (PyType_Check(selftype) || PyModule_Check(selftype)) - ? selftype - : reinterpret_cast<PyObject *>(Py_TYPE(selftype)); - Py_INCREF(obtype_mod); - return obtype_mod; -} - -PyObject *_get_class_of_sm(PyObject *ob_sm) -{ - AutoDecRef func(PyObject_GetAttr(ob_sm, PyMagicName::func())); - return _get_class_of_cf(func); -} - -PyObject *_get_class_of_descr(PyObject *ob) -{ - return PyObject_GetAttr(ob, PyMagicName::objclass()); -} - -PyObject *_address_to_stringlist(PyObject *numkey) -{ - /* - * This is a tiny optimization that saves initialization time. - * Instead of creating all Python strings during the call to - * `PySide_BuildSignatureArgs`, we store the address of the stringlist. - * When needed in `PySide_BuildSignatureProps`, the strings are - * finally materialized. - */ - ssize_t address = PyNumber_AsSsize_t(numkey, PyExc_ValueError); - if (address == -1 && PyErr_Occurred()) - return nullptr; - char **sig_strings = reinterpret_cast<char **>(address); - PyObject *res_list = PyList_New(0); - if (res_list == nullptr) - return nullptr; - for (; *sig_strings != nullptr; ++sig_strings) { - char *sig_str = *sig_strings; - AutoDecRef pystr(Py_BuildValue("s", sig_str)); - if (pystr.isNull() || PyList_Append(res_list, pystr) < 0) - return nullptr; - } - return res_list; -} - -static int _build_func_to_type(PyObject *obtype) -{ - /* - * There is no general way to directly get the type of a static method. - * On Python 3, the type is hidden in an unused pointer in the - * PyCFunction structure, but the Limited API does not allow to access - * this, either. - * - * In the end, it was easier to avoid such tricks and build an explicit - * mapping from function to type. - * - * We walk through the method list of the type - * and record the mapping from static method to this type in a dict. - * We also check for hidden methods, see below. - */ - auto *type = reinterpret_cast<PyTypeObject *>(obtype); - PyObject *dict = type->tp_dict; - PyMethodDef *meth = type->tp_methods; - - if (meth == nullptr) - return 0; - - for (; meth->ml_name != nullptr; meth++) { - /* - * It is possible that a method is overwritten by another - * attribute with the same name. This case was obviously provoked - * explicitly in "testbinding.TestObject.staticMethodDouble", - * where instead of the method a "PySide2.QtCore.Signal" object - * was in the dict. - * This overlap is also found in regular PySide under - * "PySide2.QtCore.QProcess.error" where again a signal object is - * returned. These hidden methods will be opened for the - * signature module by adding them under the name - * "{name}.overload". - */ - PyObject *descr = PyDict_GetItemString(dict, meth->ml_name); - PyObject *look_attr = meth->ml_flags & METH_STATIC ? PyMagicName::func() - : PyMagicName::name(); - int check_name = meth->ml_flags & METH_STATIC ? 0 : 1; - if (descr == nullptr) - return -1; - - // We first check all methods if one is hidden by something else. - AutoDecRef look(PyObject_GetAttr(descr, look_attr)); - AutoDecRef given(Py_BuildValue("s", meth->ml_name)); - if (look.isNull() - || (check_name && PyObject_RichCompareBool(look, given, Py_EQ) != 1)) { - PyErr_Clear(); - AutoDecRef cfunc(PyCFunction_NewEx( - meth, reinterpret_cast<PyObject *>(type), nullptr)); - if (cfunc.isNull()) - return -1; - if (meth->ml_flags & METH_STATIC) - descr = PyStaticMethod_New(cfunc); - else - descr = PyDescr_NewMethod(type, meth); - if (descr == nullptr) - return -1; - char mangled_name[200]; - strcpy(mangled_name, meth->ml_name); - strcat(mangled_name, ".overload"); - if (PyDict_SetItemString(dict, mangled_name, descr) < 0) - return -1; - if (meth->ml_flags & METH_STATIC) { - // This is the special case where a static method is hidden. - AutoDecRef special(Py_BuildValue("(Os)", cfunc.object(), "overload")); - if (PyDict_SetItem(pyside_globals->map_dict, special, obtype) < 0) - return -1; - } - if (PyDict_SetItemString(pyside_globals->map_dict, mangled_name, obtype) < 0) - return -1; - continue; - } - // Then we insert the mapping for static methods. - if (meth->ml_flags & METH_STATIC) { - if (PyDict_SetItem(pyside_globals->map_dict, look, obtype) < 0) - return -1; - } - } - return 0; -} - -int _finish_nested_classes(PyObject *obdict) -{ - PyObject *key, *value, *obtype; - PyTypeObject *subtype; - Py_ssize_t pos = 0; - - if (obdict == nullptr) - return -1; - while (PyDict_Next(obdict, &pos, &key, &value)) { - if (PyType_Check(value)) { - obtype = value; - if (_build_func_to_type(obtype) < 0) - return -1; - // now continue with nested cases - subtype = reinterpret_cast<PyTypeObject *>(obtype); - if (_finish_nested_classes(subtype->tp_dict) < 0) - return -1; - } - } - return 0; -} - -} // extern "C" diff --git a/sources/shiboken2/libshiboken/signature/signature_p.h b/sources/shiboken2/libshiboken/signature/signature_p.h deleted file mode 100644 index ef7846472..000000000 --- a/sources/shiboken2/libshiboken/signature/signature_p.h +++ /dev/null @@ -1,107 +0,0 @@ -/**************************************************************************** -** -** Copyright (C) 2020 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$ -** -****************************************************************************/ - -#ifndef SIGNATURE_IMPL_H -#define SIGNATURE_IMPL_H - -#include "signature.h" - -extern "C" { - -// signature_globals.cpp - -typedef struct safe_globals_struc { - // init part 1: get arg_dict - PyObject *helper_module; - PyObject *arg_dict; - PyObject *map_dict; - PyObject *value_dict; // for writing signatures - PyObject *feature_dict; // registry for PySide.support.__feature__ - // init part 2: run module - PyObject *pyside_type_init_func; - PyObject *create_signature_func; - PyObject *seterror_argument_func; - PyObject *make_helptext_func; - PyObject *finish_import_func; -} safe_globals_struc, *safe_globals; - -extern safe_globals pyside_globals; -extern PyMethodDef signature_methods[]; - -void init_module_1(void); -void init_module_2(void); - -// signature.cpp - -PyObject *GetTypeKey(PyObject *ob); - -PyObject *GetSignature_Function(PyObject *, PyObject *); -PyObject *GetSignature_TypeMod(PyObject *, PyObject *); -PyObject *GetSignature_Wrapper(PyObject *, PyObject *); - -PyObject *get_signature_intern(PyObject *ob, PyObject *modifier); -PyObject *PySide_BuildSignatureProps(PyObject *class_mod); -PyObject *GetClassOrModOf(PyObject *ob); - -// signature_extend.cpp - -PyObject *pyside_cf_get___signature__(PyObject *func, PyObject *modifier); -PyObject *pyside_sm_get___signature__(PyObject *sm, PyObject *modifier); -PyObject *pyside_md_get___signature__(PyObject *ob_md, PyObject *modifier); -PyObject *pyside_wd_get___signature__(PyObject *ob, PyObject *modifier); -PyObject *pyside_tp_get___signature__(PyObject *obtype_mod, PyObject *modifier); - -int PySide_PatchTypes(void); -PyObject *pyside_tp_get___doc__(PyObject *tp); - -// signature_helper.cpp - -PyObject *_get_qualname(PyObject *ob); -int add_more_getsets(PyTypeObject *type, PyGetSetDef *gsp, PyObject **doc_descr); -PyObject *name_key_to_func(PyObject *ob); -int insert_snake_case_variants(PyObject *dict); -PyObject *_get_class_of_cf(PyObject *ob_cf); -PyObject *_get_class_of_sm(PyObject *ob_sm); -PyObject *_get_class_of_descr(PyObject *ob); -PyObject *_address_to_stringlist(PyObject *numkey); -int _finish_nested_classes(PyObject *dict); - -} // extern "C" - -#endif // SIGNATURE_IMPL_H diff --git a/sources/shiboken2/libshiboken/threadstatesaver.cpp b/sources/shiboken2/libshiboken/threadstatesaver.cpp deleted file mode 100644 index 085535fd7..000000000 --- a/sources/shiboken2/libshiboken/threadstatesaver.cpp +++ /dev/null @@ -1,71 +0,0 @@ -/**************************************************************************** -** -** Copyright (C) 2016 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$ -** -****************************************************************************/ - -#include "threadstatesaver.h" - -namespace Shiboken -{ - -ThreadStateSaver::ThreadStateSaver() = default; - -ThreadStateSaver::~ThreadStateSaver() -{ - restore(); -} - -void ThreadStateSaver::save() -{ -#if PY_VERSION_HEX >= 0x0309000 - if (Py_IsInitialized()) -#else - if (PyEval_ThreadsInitialized()) -#endif - m_threadState = PyEval_SaveThread(); -} - -void ThreadStateSaver::restore() -{ - if (m_threadState) { - PyEval_RestoreThread(m_threadState); - m_threadState = nullptr; - } -} - -} // namespace Shiboken - diff --git a/sources/shiboken2/libshiboken/threadstatesaver.h b/sources/shiboken2/libshiboken/threadstatesaver.h deleted file mode 100644 index ddfbcb93b..000000000 --- a/sources/shiboken2/libshiboken/threadstatesaver.h +++ /dev/null @@ -1,68 +0,0 @@ -/**************************************************************************** -** -** Copyright (C) 2016 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$ -** -****************************************************************************/ - -#ifndef THREADSTATESAVER_H -#define THREADSTATESAVER_H - -#include "sbkpython.h" -#include <shibokenmacros.h> - -namespace Shiboken -{ - -class LIBSHIBOKEN_API ThreadStateSaver -{ -public: - ThreadStateSaver(const ThreadStateSaver &) = delete; - ThreadStateSaver(ThreadStateSaver &&) = delete; - ThreadStateSaver &operator=(const ThreadStateSaver &) = delete; - ThreadStateSaver &operator=(ThreadStateSaver &&) = delete; - - ThreadStateSaver(); - ~ThreadStateSaver(); - void save(); - void restore(); -private: - PyThreadState *m_threadState = nullptr; -}; - -} // namespace Shiboken - -#endif // THREADSTATESAVER_H - diff --git a/sources/shiboken2/libshiboken/tmp-referencetopython/sbkconverter.cpp b/sources/shiboken2/libshiboken/tmp-referencetopython/sbkconverter.cpp deleted file mode 100644 index ab205e215..000000000 --- a/sources/shiboken2/libshiboken/tmp-referencetopython/sbkconverter.cpp +++ /dev/null @@ -1,216 +0,0 @@ -/**************************************************************************** -** -** Copyright (C) 2016 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$ -** -****************************************************************************/ - -#include "sbkconverter.h" -#include "sbkconverter_p.h" -#include "basewrapper_p.h" - -#include "sbkdbg.h" - -namespace Shiboken { -namespace Conversions { - -static SbkConverter *createConverterObject(PyTypeObject *type, - PythonToCppFunc toCppPointerConvFunc, - IsConvertibleToCppFunc toCppPointerCheckFunc, - CppToPythonFunc pointerToPythonFunc, - CppToPythonFunc copyToPythonFunc) -{ - SbkConverter *converter = new SbkConverter; - converter->pythonType = type; - - converter->pointerToPython = pointerToPythonFunc; - converter->copyToPython = copyToPythonFunc; - - converter->toCppPointerConversion = std::make_pair(toCppPointerCheckFunc, toCppPointerConvFunc); - converter->toCppConversions.clear(); - - return converter; -} - -SbkConverter *createConverter(SbkObjectType *type, - PythonToCppFunc toCppPointerConvFunc, - IsConvertibleToCppFunc toCppPointerCheckFunc, - CppToPythonFunc pointerToPythonFunc, - CppToPythonFunc copyToPythonFunc) -{ - SbkConverter *converter = createConverterObject(reinterpret_cast<PyTypeObject *>(type), - toCppPointerConvFunc, toCppPointerCheckFunc, - pointerToPythonFunc, copyToPythonFunc); - type->d->converter = converter; - return converter; -} - -void deleteConverter(SbkConverter *converter) -{ - if (converter) { - converter->toCppConversions.clear(); - delete converter; - } -} - -void addPythonToCppValueConversion(SbkConverter *converter, - PythonToCppFunc pythonToCppFunc, - IsConvertibleToCppFunc isConvertibleToCppFunc) -{ - converter->toCppConversions.push_back(std::make_pair(isConvertibleToCppFunc, pythonToCppFunc)); -} -void addPythonToCppValueConversion(SbkObjectType *type, - PythonToCppFunc pythonToCppFunc, - IsConvertibleToCppFunc isConvertibleToCppFunc) -{ - addPythonToCppValueConversion(type->d->converter, pythonToCppFunc, isConvertibleToCppFunc); -} - -PyObject *pointerToPython(SbkObjectType *type, const void *cppIn) -{ - if (!cppIn) - Py_RETURN_NONE; - return type->d->converter->pointerToPython(cppIn); -} - -static inline PyObject *CopyCppToPython(SbkConverter *converter, const void *cppIn) -{ - assert(cppIn); - return converter->copyToPython(cppIn); -} -PyObject *copyToPython(SbkObjectType *type, const void *cppIn) -{ - return CopyCppToPython(type->d->converter, cppIn); -} -PyObject *toPython(SbkConverter *converter, const void *cppIn) -{ - return CopyCppToPython(converter, cppIn); -} - -PyObject *referenceToPython(SbkObjectType *type, const void *cppIn) -{ - assert(cppIn); - PyObject *pyOut = (PyObject *)BindingManager::instance().retrieveWrapper(cppIn); - if (pyOut) { - Py_INCREF(pyOut); - return pyOut; - } - // If it is Value Type, return a copy of the C++ object. - if (type->d->converter->copyToPython) - return type->d->converter->copyToPython(cppIn); - // If it is an Object Type, return a copy of the C++ object. - return type->d->converter->pointerToPython(cppIn); -} - -PythonToCppFunc isPythonToCppPointerConvertible(SbkObjectType *type, PyObject *pyIn) -{ - assert(pyIn); - return type->d->converter->toCppPointerConversion.first(pyIn); -} - -static inline PythonToCppFunc IsPythonToCppConvertible(SbkConverter *converter, PyObject *pyIn) -{ - assert(pyIn); - ToCppConversionList &convs = converter->toCppConversions; - for (ToCppConversionList::iterator conv = convs.begin(); conv != convs.end(); ++conv) { - PythonToCppFunc toCppFunc = 0; - if ((toCppFunc = (*conv).first(pyIn))) - return toCppFunc; - } - return 0; -} -PythonToCppFunc isPythonToCppValueConvertible(SbkObjectType *type, PyObject *pyIn) -{ - return IsPythonToCppConvertible(type->d->converter, pyIn); -} -PythonToCppFunc isPythonToCppConvertible(SbkConverter *converter, PyObject *pyIn) -{ - return IsPythonToCppConvertible(converter, pyIn); -} - -PythonToCppFunc isPythonToCppReferenceConvertible(SbkObjectType *type, PyObject *pyIn) -{ - if (pyIn != Py_None) { - PythonToCppFunc toCpp = isPythonToCppPointerConvertible(type, pyIn); - if (toCpp) - return toCpp; - } - return isPythonToCppValueConvertible(type, pyIn); -} - -void nonePythonToCppNullPtr(PyObject *, void *cppOut) -{ - assert(cppOut); - *reinterpret_cast<void **>(cppOut) = nullptr; -} - -void pythonToCppPointer(SbkObjectType *type, PyObject *pyIn, void *cppOut) -{ - assert(pyIn); - assert(cppOut); - SbkObjectType *inType = (SbkObjectType *)Py_TYPE(pyIn); - if (ObjectType::hasCast(inType)) { - *reinterpret_cast<void **>(cppOut) = - ObjectType::cast(inType, reinterpret_cast<SbkObject *>(pyIn), reinterpret_cast<PyTypeObject *>(type)); - } else { - *reinterpret_cast<void **>(cppOut) = - Object::cppPointer(reinterpret_cast<SbkObject *>(pyIn), reinterpret_cast<PyTypeObject *>(type)); - } -} - -bool isImplicitConversion(SbkObjectType *type, PythonToCppFunc toCppFunc) -{ - // This is the Object Type or Value Type conversion that only - // retrieves the C++ pointer held in the Python wrapper. - if (toCppFunc == type->d->converter->toCppPointerConversion.second) - return false; - - // Object Types doesn't have any kind of value conversion, - // only C++ pointer retrieval. - if (type->d->converter->toCppConversions.empty()) - return false; - - // The first conversion of the non-pointer conversion list is - // a Value Type's copy to C++ function, which is not an implicit - // conversion. - // Otherwise it must be one of the implicit conversions. - // Note that we don't check if the Python to C++ conversion is in - // the list of the type's conversions, for it is expected that the - // caller knows what he's doing. - ToCppConversionList::iterator conv = type->d->converter->toCppConversions.begin(); - return toCppFunc != (*conv).second; -} - -} } // namespace Shiboken::Conversions diff --git a/sources/shiboken2/libshiboken/tmp-referencetopython/sbkconverter.h b/sources/shiboken2/libshiboken/tmp-referencetopython/sbkconverter.h deleted file mode 100644 index 3578e4039..000000000 --- a/sources/shiboken2/libshiboken/tmp-referencetopython/sbkconverter.h +++ /dev/null @@ -1,191 +0,0 @@ -/**************************************************************************** -** -** Copyright (C) 2016 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$ -** -****************************************************************************/ - -#ifndef SBK_CONVERTER_H -#define SBK_CONVERTER_H - -#include <limits> -#include "sbkpython.h" -#include "shibokenmacros.h" -#include "basewrapper.h" - -extern "C" -{ - -/** - * SbkConverter is used to perform type conversions from C++ - * to Python and vice-versa;.and it is also used for type checking. - * SbkConverter is a private structure that must be accessed - * using the functions provided by the converter API. - */ -struct SbkConverter; - -/** - * Given a void pointer to a C++ object, this function must return - * the proper Python object. It may be either an existing wrapper - * for the C++ object, or a newly create one. Or even the Python - * equivalent of the C++ value passed in the argument. - * - * C++ -> Python - */ -typedef PyObject *(*CppToPythonFunc)(const void *); - -/** - * This function converts a Python object to a C++ value, it may be - * a pointer, value, class, container or primitive type, passed via - * a void pointer, that will be cast properly inside the function. - * This function is usually returned by an IsConvertibleToCppFunc - * function, or obtained knowing the type of the Python object input, - * thus it will not check the Python object type, and will expect - * the void pointer to be pointing to a proper variable. - * - * Python -> C++ - */ -typedef void (*PythonToCppFunc)(PyObject *,void *); - -/** - * Checks if the Python object passed in the argument is convertible to a - * C++ type defined inside the function, it returns the converter function - * that will transform a Python argument into a C++ value. - * It returns NULL if the Python object is not convertible to the C++ type - * that the function represents. - * - * Python -> C++ ? - */ -typedef PythonToCppFunc (*IsConvertibleToCppFunc)(PyObject *); - -} // extern "C" - - -namespace Shiboken { -namespace Conversions { - -/** - * Creates a converter for a wrapper type. - * \param type A Shiboken.ObjectType that will receive the new converter. - * \param toCppPointerConvFunc Function to retrieve the C++ pointer held by a Python wrapper. - * \param toCppPointerCheckFunc Check and return the retriever function of the C++ pointer held by a Python wrapper. - * \param pointerToPythonFunc Function to convert a C++ object to a Python \p type wrapper, keeping their identity. - * \param copyToPythonFunc Function to convert a C++ object to a Python \p type, copying the object. - * \returns The new converter referred by the wrapper \p type. - */ -LIBSHIBOKEN_API SbkConverter *createConverter(SbkObjectType *type, - PythonToCppFunc toCppPointerConvFunc, - IsConvertibleToCppFunc toCppPointerCheckFunc, - CppToPythonFunc pointerToPythonFunc, - CppToPythonFunc copyToPythonFunc = 0); - -LIBSHIBOKEN_API void deleteConverter(SbkConverter *converter); - -/** - * Adds a new conversion of a Python object to a C++ value. - * This is used in copy and implicit conversions. - */ -LIBSHIBOKEN_API void addPythonToCppValueConversion(SbkConverter *converter, - PythonToCppFunc pythonToCppFunc, - IsConvertibleToCppFunc isConvertibleToCppFunc); -LIBSHIBOKEN_API void addPythonToCppValueConversion(SbkObjectType *type, - PythonToCppFunc pythonToCppFunc, - IsConvertibleToCppFunc isConvertibleToCppFunc); - -// C++ -> Python --------------------------------------------------------------------------- - -/** - * Retrieves the Python wrapper object for the given \p cppIn C++ pointer object. - * This function is used only for Value and Object Types. - * Example usage: - * TYPE *var; - * PyObject *pyVar = pointerToPython(SBKTYPE, &var); - */ -LIBSHIBOKEN_API PyObject *pointerToPython(SbkObjectType *type, const void *cppIn); - -/** - * Retrieves the Python wrapper object for the given C++ value pointed by \p cppIn. - * This function is used only for Value Types. - * Example usage: - * TYPE var; - * PyObject *pyVar = copyToPython(SBKTYPE, &var); - */ -LIBSHIBOKEN_API PyObject *copyToPython(SbkObjectType *type, const void *cppIn); - -// TODO:WRITEDOCSTRING - used only for Value Types - cppIn must point to a value -/** - * Retrieves the Python wrapper object for the given C++ reference pointed by \p cppIn. - * This function is used only for Value and Object Types. - * It differs from pointerToPython() for not checking for a NULL pointer. - * Example usage: - * TYPE &var = SOMETHING; - * PyObject *pyVar = copyToPython(SBKTYPE, &var); - */ -LIBSHIBOKEN_API PyObject *referenceToPython(SbkObjectType *type, const void *cppIn); - -// TODO:WRITEDOCSTRING - used only for Primitives and Containers (and Value Types) - cppIn must point to a primitive, container or value type -/// This is the same as copyToPython function. -LIBSHIBOKEN_API PyObject *toPython(SbkConverter *converter, const void *cppIn); - -// Python -> C++ convertibility checks ----------------------------------------------------- - -// TODO:WRITEDOCSTRING -LIBSHIBOKEN_API PythonToCppFunc isPythonToCppPointerConvertible(SbkObjectType *type, PyObject *pyIn); - -// TODO:WRITEDOCSTRING- Returns a Python to C++ conversion function if true, or NULL if false. -LIBSHIBOKEN_API PythonToCppFunc isPythonToCppValueConvertible(SbkObjectType *type, PyObject *pyIn); - -// TODO:WRITEDOCSTRING- Returns a Python to C++ conversion function if true, or NULL if false. -LIBSHIBOKEN_API PythonToCppFunc isPythonToCppReferenceConvertible(SbkObjectType *type, PyObject *pyIn); - -/// This is the same as isPythonToCppValueConvertible function. -LIBSHIBOKEN_API PythonToCppFunc isPythonToCppConvertible(SbkConverter *converter, PyObject *pyIn); - -// Python -> C++ --------------------------------------------------------------------------- - -// TODO:WRITEDOCSTRING - function used by the generated [TYPE]_PythonToCpp_[TYPE]_PTR -LIBSHIBOKEN_API void pythonToCppPointer(SbkObjectType *type, PyObject *pyIn, void *cppOut); - -// TODO:WRITEDOCSTRING - function used by the generated isConvertible when the PyObject is None, -// making a C++ NULL pointer the result of the toCpp function call. -// DRAFT: When the Python object is a Py_None, it's C++ conversion is always a NULL pointer. -LIBSHIBOKEN_API void nonePythonToCppNullPtr(PyObject *, void *cppOut); - -// TODO:WRITEDOCSTRING - tells if \p toCpp is an implicit conversion. -LIBSHIBOKEN_API bool isImplicitConversion(SbkObjectType *type, PythonToCppFunc toCpp); - -} } // namespace Shiboken::Conversions - -#endif // SBK_CONVERTER_H diff --git a/sources/shiboken2/libshiboken/voidptr.cpp b/sources/shiboken2/libshiboken/voidptr.cpp deleted file mode 100644 index a21a4482f..000000000 --- a/sources/shiboken2/libshiboken/voidptr.cpp +++ /dev/null @@ -1,472 +0,0 @@ -/**************************************************************************** -** -** Copyright (C) 2017 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$ -** -****************************************************************************/ - -#include "voidptr.h" -#include "sbkconverter.h" -#include "basewrapper.h" -#include "basewrapper_p.h" - -extern "C" -{ - -// Void pointer object definition. -typedef struct { - PyObject_HEAD - void *cptr; - Py_ssize_t size; - bool isWritable; -} SbkVoidPtrObject; - -PyObject *SbkVoidPtrObject_new(PyTypeObject *type, PyObject *args, PyObject *kwds) -{ - // PYSIDE-560: It is much safer to first call a function and then do a - // type cast than to do everything in one line. The bad construct looked - // 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); - - if (self != nullptr) { - self->cptr = nullptr; - self->size = -1; - self->isWritable = false; - } - - return reinterpret_cast<PyObject *>(self); -} - -#define SbkVoidPtr_Check(op) (Py_TYPE(op) == SbkVoidPtrTypeF()) - - -int SbkVoidPtrObject_init(PyObject *self, PyObject *args, PyObject *kwds) -{ - PyObject *addressObject; - Py_ssize_t size = -1; - int isWritable = 0; - auto *sbkSelf = reinterpret_cast<SbkVoidPtrObject *>(self); - - static const char *kwlist[] = {"address", "size", "writeable", nullptr}; - - if (!PyArg_ParseTupleAndKeywords(args, kwds, "O|ni", const_cast<char **>(kwlist), - &addressObject, &size, &isWritable)) - return -1; - - // Void pointer. - if (SbkVoidPtr_Check(addressObject)) { - auto *sbkOther = reinterpret_cast<SbkVoidPtrObject *>(addressObject); - sbkSelf->cptr = sbkOther->cptr; - sbkSelf->size = sbkOther->size; - sbkSelf->isWritable = sbkOther->isWritable; - } - // Python buffer interface. - else if (PyObject_CheckBuffer(addressObject)) { - Py_buffer bufferView; - - // Bail out if the object can't provide a simple contiguous buffer. - if (PyObject_GetBuffer(addressObject, &bufferView, PyBUF_SIMPLE) < 0) - return 0; - - sbkSelf->cptr = bufferView.buf; - sbkSelf->size = bufferView.len > 0 ? bufferView.len : size; - sbkSelf->isWritable = bufferView.readonly <= 0; - - // Release the buffer. - PyBuffer_Release(&bufferView); - } - // Shiboken::Object wrapper. - else if (Shiboken::Object::checkType(addressObject)) { - auto *sbkOther = reinterpret_cast<SbkObject *>(addressObject); - sbkSelf->cptr = sbkOther->d->cptr[0]; - sbkSelf->size = size; - sbkSelf->isWritable = isWritable > 0; - } - // An integer representing an address. - else { - if (addressObject == Py_None) { - sbkSelf->cptr = nullptr; - sbkSelf->size = 0; - sbkSelf->isWritable = false; - } - - else { - void *cptr = PyLong_AsVoidPtr(addressObject); - if (PyErr_Occurred()) { - PyErr_SetString(PyExc_TypeError, - "Creating a VoidPtr object requires an address of a C++ object, " - "a wrapped Shiboken Object type, " - "an object implementing the Python Buffer interface, " - "or another VoidPtr object."); - return -1; - } - sbkSelf->cptr = cptr; - sbkSelf->size = size; - sbkSelf->isWritable = isWritable > 0; - } - } - - return 0; -} - -PyObject *SbkVoidPtrObject_richcmp(PyObject *obj1, PyObject *obj2, int op) -{ - PyObject *result = Py_False; - void *cptr1 = nullptr; - void *cptr2 = nullptr; - bool validObjects = true; - - if (SbkVoidPtr_Check(obj1)) - cptr1 = reinterpret_cast<SbkVoidPtrObject *>(obj1)->cptr; - else - validObjects = false; - - if (SbkVoidPtr_Check(obj2)) - cptr2 = reinterpret_cast<SbkVoidPtrObject *>(obj2)->cptr; - else - validObjects = false; - - if (validObjects) { - switch (op) { - case Py_EQ: if (cptr1 == cptr2) result = Py_True; break; - case Py_NE: if (cptr1 != cptr2) result = Py_True; break; - case Py_LT: break; - case Py_LE: break; - case Py_GT: break; - case Py_GE: break; - } - } - - Py_INCREF(result); - return result; -} - -PyObject *SbkVoidPtrObject_int(PyObject *v) -{ - auto *sbkObject = reinterpret_cast<SbkVoidPtrObject *>(v); - return PyLong_FromVoidPtr(sbkObject->cptr); -} - -PyObject *toBytes(PyObject *self, PyObject *args) -{ - auto *sbkObject = reinterpret_cast<SbkVoidPtrObject *>(self); - if (sbkObject->size < 0) { - PyErr_SetString(PyExc_IndexError, "VoidPtr does not have a size set."); - return nullptr; - } - PyObject *bytes = PyBytes_FromStringAndSize(reinterpret_cast<const char *>(sbkObject->cptr), - sbkObject->size); - Py_XINCREF(bytes); - return bytes; -} - -static struct PyMethodDef SbkVoidPtrObject_methods[] = { - {"toBytes", toBytes, METH_NOARGS}, - {nullptr} -}; - -static Py_ssize_t SbkVoidPtrObject_length(PyObject *v) -{ - auto *sbkObject = reinterpret_cast<SbkVoidPtrObject *>(v); - if (sbkObject->size < 0) { - PyErr_SetString(PyExc_IndexError, "VoidPtr does not have a size set."); - return -1; - } - - return sbkObject->size; -} - -static const char trueString[] = "True" ; -static const char falseString[] = "False" ; - -PyObject *SbkVoidPtrObject_repr(PyObject *v) -{ - - - auto *sbkObject = reinterpret_cast<SbkVoidPtrObject *>(v); - PyObject *s = PyUnicode_FromFormat("%s(%p, %zd, %s)", - Py_TYPE(sbkObject)->tp_name, - sbkObject->cptr, - sbkObject->size, - sbkObject->isWritable ? trueString : falseString); - Py_XINCREF(s); - return s; -} - -PyObject *SbkVoidPtrObject_str(PyObject *v) -{ - auto *sbkObject = reinterpret_cast<SbkVoidPtrObject *>(v); - PyObject *s = PyUnicode_FromFormat("%s(Address %p, Size %zd, isWritable %s)", - Py_TYPE(sbkObject)->tp_name, - sbkObject->cptr, - sbkObject->size, - sbkObject->isWritable ? trueString : falseString); - Py_XINCREF(s); - return s; -} - - -static int SbkVoidPtrObject_getbuffer(PyObject *obj, Py_buffer *view, int flags) -{ - if (view == nullptr) - return -1; - - auto *sbkObject = reinterpret_cast<SbkVoidPtrObject *>(obj); - if (sbkObject->size < 0) - return -1; - - int readonly = sbkObject->isWritable ? 0 : 1; - if (((flags & PyBUF_WRITABLE) == PyBUF_WRITABLE) && - (readonly == 1)) { - PyErr_SetString(PyExc_BufferError, - "Object is not writable."); - return -1; - } - - view->obj = obj; - if (obj) - Py_XINCREF(obj); - view->buf = sbkObject->cptr; - view->len = sbkObject->size; - view->readonly = readonly; - view->itemsize = 1; - view->format = nullptr; - if ((flags & PyBUF_FORMAT) == PyBUF_FORMAT) - view->format = const_cast<char *>("B"); - view->ndim = 1; - view->shape = nullptr; - if ((flags & PyBUF_ND) == PyBUF_ND) - view->shape = &(view->len); - view->strides = nullptr; - if ((flags & PyBUF_STRIDES) == PyBUF_STRIDES) - view->strides = &(view->itemsize); - view->suboffsets = nullptr; - view->internal = nullptr; - return 0; -} - -#if PY_VERSION_HEX < 0x03000000 - -static Py_ssize_t SbkVoidPtrObject_readbufferproc(PyObject *self, Py_ssize_t segment, void **ptrptr) -{ - if (segment || !Shiboken::Object::isValid(self)) - return -1; - - SbkVoidPtrObject *sbkObject = reinterpret_cast<SbkVoidPtrObject *>(self); - *ptrptr = reinterpret_cast<void *>(sbkObject->cptr); - return sbkObject->size; -} - -static Py_ssize_t SbkVoidPtrObject_segcountproc(PyObject *self, Py_ssize_t *lenp) -{ - if (lenp) { - SbkVoidPtrObject *sbkObject = reinterpret_cast<SbkVoidPtrObject *>(self); - *lenp = sbkObject->size; - } - return 1; -} - -PyBufferProcs SbkVoidPtrObjectBufferProc = { - &SbkVoidPtrObject_readbufferproc, // bf_getreadbuffer - (writebufferproc)&SbkVoidPtrObject_readbufferproc, // bf_getwritebuffer - &SbkVoidPtrObject_segcountproc, // bf_getsegcount - (charbufferproc)&SbkVoidPtrObject_readbufferproc, // bf_getcharbuffer - (getbufferproc)SbkVoidPtrObject_getbuffer, // bf_getbuffer -}; - -#else - -static PyBufferProcs SbkVoidPtrObjectBufferProc = { - (getbufferproc)SbkVoidPtrObject_getbuffer, // bf_getbuffer - (releasebufferproc)nullptr // bf_releasebuffer -}; - -#endif - -// Void pointer type definition. -static PyType_Slot SbkVoidPtrType_slots[] = { - {Py_tp_repr, (void *)SbkVoidPtrObject_repr}, - {Py_nb_int, (void *)SbkVoidPtrObject_int}, - {Py_sq_length, (void *)SbkVoidPtrObject_length}, - {Py_tp_str, (void *)SbkVoidPtrObject_str}, - {Py_tp_richcompare, (void *)SbkVoidPtrObject_richcmp}, - {Py_tp_init, (void *)SbkVoidPtrObject_init}, - {Py_tp_new, (void *)SbkVoidPtrObject_new}, - {Py_tp_dealloc, (void *)Sbk_object_dealloc}, - {Py_tp_methods, (void *)SbkVoidPtrObject_methods}, - {0, nullptr} -}; -static PyType_Spec SbkVoidPtrType_spec = { - "2:shiboken2.shiboken2.VoidPtr", - sizeof(SbkVoidPtrObject), - 0, - Py_TPFLAGS_DEFAULT, - SbkVoidPtrType_slots, -}; - - -} - -PyTypeObject *SbkVoidPtrTypeF(void) -{ - static PyTypeObject *type = nullptr; - if (!type) { - type = reinterpret_cast<PyTypeObject *>(SbkType_FromSpec(&SbkVoidPtrType_spec)); -#if PY_VERSION_HEX < 0x03000000 - type->tp_as_buffer = &SbkVoidPtrObjectBufferProc; - type->tp_flags |= Py_TPFLAGS_HAVE_NEWBUFFER; -#else - PepType_AS_BUFFER(type) = &SbkVoidPtrObjectBufferProc; -#endif - } - return type; -} - -namespace VoidPtr { - -static int voidPointerInitialized = false; - -void init() -{ - if (PyType_Ready(reinterpret_cast<PyTypeObject *>(SbkVoidPtrTypeF())) < 0) - Py_FatalError("[libshiboken] Failed to initialize Shiboken.VoidPtr type."); - else - voidPointerInitialized = true; -} - -void addVoidPtrToModule(PyObject *module) -{ - if (voidPointerInitialized) { - Py_INCREF(SbkVoidPtrTypeF()); - PyModule_AddObject(module, PepType_GetNameStr(SbkVoidPtrTypeF()), - reinterpret_cast<PyObject *>(SbkVoidPtrTypeF())); - } -} - -static PyObject *createVoidPtr(void *cppIn, Py_ssize_t size = 0, bool isWritable = false) -{ - if (!cppIn) - Py_RETURN_NONE; - - SbkVoidPtrObject *result = PyObject_New(SbkVoidPtrObject, SbkVoidPtrTypeF()); - if (!result) - Py_RETURN_NONE; - - result->cptr = cppIn; - result->size = size; - result->isWritable = isWritable; - - return reinterpret_cast<PyObject *>(result); -} - -static PyObject *toPython(const void *cppIn) -{ - return createVoidPtr(const_cast<void *>(cppIn)); -} - -static void VoidPtrToCpp(PyObject *pyIn, void *cppOut) -{ - auto *sbkIn = reinterpret_cast<SbkVoidPtrObject *>(pyIn); - *reinterpret_cast<void **>(cppOut) = sbkIn->cptr; -} - -static PythonToCppFunc VoidPtrToCppIsConvertible(PyObject *pyIn) -{ - return SbkVoidPtr_Check(pyIn) ? VoidPtrToCpp : nullptr; -} - -static void SbkObjectToCpp(PyObject *pyIn, void *cppOut) -{ - auto *sbkIn = reinterpret_cast<SbkObject *>(pyIn); - *reinterpret_cast<void **>(cppOut) = sbkIn->d->cptr[0]; -} - -static PythonToCppFunc SbkObjectToCppIsConvertible(PyObject *pyIn) -{ - return Shiboken::Object::checkType(pyIn) ? SbkObjectToCpp : nullptr; -} - -static void PythonBufferToCpp(PyObject *pyIn, void *cppOut) -{ - if (PyObject_CheckBuffer(pyIn)) { - Py_buffer bufferView; - - // Bail out if the object can't provide a simple contiguous buffer. - if (PyObject_GetBuffer(pyIn, &bufferView, PyBUF_SIMPLE) < 0) - return; - - *reinterpret_cast<void **>(cppOut) = bufferView.buf; - - // Release the buffer. - PyBuffer_Release(&bufferView); - } -} - -static PythonToCppFunc PythonBufferToCppIsConvertible(PyObject *pyIn) -{ - if (PyObject_CheckBuffer(pyIn)) { - Py_buffer bufferView; - - // Bail out if the object can't provide a simple contiguous buffer. - if (PyObject_GetBuffer(pyIn, &bufferView, PyBUF_SIMPLE) < 0) - return nullptr; - - // Release the buffer. - PyBuffer_Release(&bufferView); - - return PythonBufferToCpp; - } - return nullptr; -} - -SbkConverter *createConverter() -{ - SbkConverter *converter = Shiboken::Conversions::createConverter(SbkVoidPtrTypeF(), toPython); - Shiboken::Conversions::addPythonToCppValueConversion(converter, - VoidPtrToCpp, - VoidPtrToCppIsConvertible); - Shiboken::Conversions::addPythonToCppValueConversion(converter, - SbkObjectToCpp, - SbkObjectToCppIsConvertible); - Shiboken::Conversions::addPythonToCppValueConversion(converter, - PythonBufferToCpp, - PythonBufferToCppIsConvertible); - return converter; -} - -} // namespace VoidPtr diff --git a/sources/shiboken2/libshiboken/voidptr.h b/sources/shiboken2/libshiboken/voidptr.h deleted file mode 100644 index e74c1045e..000000000 --- a/sources/shiboken2/libshiboken/voidptr.h +++ /dev/null @@ -1,65 +0,0 @@ -/**************************************************************************** -** -** Copyright (C) 2017 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$ -** -****************************************************************************/ - -#ifndef VOIDPTR_H -#define VOIDPTR_H - -#include "sbkpython.h" -#include "shibokenmacros.h" -#include "sbkconverter.h" - -extern "C" -{ - -// Void pointer type declaration. -extern LIBSHIBOKEN_API PyTypeObject *SbkVoidPtrTypeF(void); - -} // extern "C" - -namespace VoidPtr -{ - -void init(); -SbkConverter *createConverter(); -LIBSHIBOKEN_API void addVoidPtrToModule(PyObject *module); - -} - - -#endif // VOIDPTR_H |