diff options
Diffstat (limited to 'sources/shiboken2/libshiboken')
58 files changed, 0 insertions, 15349 deletions
diff --git a/sources/shiboken2/libshiboken/CMakeLists.txt b/sources/shiboken2/libshiboken/CMakeLists.txt deleted file mode 100644 index 7cbb22978..000000000 --- a/sources/shiboken2/libshiboken/CMakeLists.txt +++ /dev/null @@ -1,150 +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("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" - OUTPUT "${CMAKE_CURRENT_BINARY_DIR}/embed/signature.inc" - 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 -bindingmanager.cpp -threadstatesaver.cpp -shibokenbuffer.cpp -signature.cpp -qapp_macro.cpp -pep384impl.cpp -voidptr.cpp -typespec.cpp -bufferprocs_py37.cpp -embed/signature_bootstrap.inc -embed/signature.inc -) - -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 LIBSHIBOKEN_EXPORTS) - -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 - shiboken.h - shibokenmacros.h - threadstatesaver.h - shibokenbuffer.h - sbkpython.h - pep384impl.h - signature.h - qapp_macro.h - voidptr.h - typespec.h - bufferprocs_py37.h - "${CMAKE_CURRENT_BINARY_DIR}/sbkversion.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 d3353b1e4..000000000 --- a/sources/shiboken2/libshiboken/autodecref.h +++ /dev/null @@ -1,109 +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) - { - Py_XDECREF(m_pyObj); - m_pyObj = other; - } -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 b9f6735d8..000000000 --- a/sources/shiboken2/libshiboken/basewrapper.cpp +++ /dev/null @@ -1,1645 +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 "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" - -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" -{ - -static void SbkObjectTypeDealloc(PyObject *pyObj); -static PyObject *SbkObjectTypeTpNew(PyTypeObject *metatype, PyObject *args, PyObject *kwds); - -// 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__}, - {nullptr} // Sentinel -}; - -static PyType_Slot SbkObjectType_Type_slots[] = { - {Py_tp_dealloc, reinterpret_cast<void *>(SbkObjectTypeDealloc)}, - {Py_tp_setattro, reinterpret_cast<void *>(PyObject_GenericSetAttr)}, - {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)}, - {0, nullptr} -}; -static PyType_Spec SbkObjectType_Type_spec = { - "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 - * - * 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. - */ - -static PyCFunction 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__", (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 -get_old_tp_new_wrapper(void) -{ - // We get the old tp_new_wrapper from any initialized type. - PyTypeObject *type = &PyType_Type; - PyObject *dict = type->tp_dict; - PyObject *key, *func = nullptr; - Py_ssize_t pos = 0; - while (PyDict_Next(dict, &pos, &key, &func)) { - char *name = PyString_AsString(key); - if (strcmp(name, "__new__") == 0) { - break; - } - } - if (func == nullptr) - return -1; - PyCFunctionObject *pycf_ob = reinterpret_cast<PyCFunctionObject *>(func); - old_tp_new_wrapper = pycf_ob->m_ml->ml_meth; - return 0; -} - -static int -add_tp_new_wrapper(PyTypeObject *type) -{ - // get the original tp_new_wrapper - if (old_tp_new_wrapper == nullptr && get_old_tp_new_wrapper() < 0) - return -1; - // initialize tp_dict - if (type->tp_dict == nullptr) - type->tp_dict = PyDict_New(); - if (type->tp_dict == nullptr) - return -1; - PyObject *ob_type = reinterpret_cast<PyObject *>(type); - Shiboken::AutoDecRef func(PyCFunction_New(tp_new_methoddef, ob_type)); - if (func.isNull()) - return -1; - if (PyDict_SetItemString(type->tp_dict, "__new__", func)) - return -1; - return 0; -} -/*****************************************************************************/ -#endif // PY_VERSION_HEX < 0x03000000 - - -PyTypeObject *SbkObjectType_TypeF(void) -{ - static PyTypeObject *type = nullptr; - if (!type) { - SbkObjectType_Type_spec.basicsize = - PepHeapType_SIZE + sizeof(SbkObjectTypePrivate); - type = reinterpret_cast<PyTypeObject *>(PyType_FromSpec(&SbkObjectType_Type_spec)); -#if PY_VERSION_HEX < 0x03000000 - if (add_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 PyType_Slot SbkObject_Type_slots[] = { - {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 = { - "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 *>(PyType_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 = (PyType_GetSlot(pyType, Py_tp_dealloc) == SbkDeallocWrapper - || PyType_GetSlot(pyType, Py_tp_dealloc) == SbkDeallocWrapperWithPrivateDtor); - - // 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; - } - } - - 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); - } - - if (needTypeDecref) - 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. - MakeSingletonQAppWrapper(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 -} - -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); -#ifndef IS_PY3K - if (PyClass_Check(baseType)) { - PyErr_Format(PyExc_TypeError, "Invalid base class used in type %s. " - "PySide only support multiple inheritance from python new style class.", metatype->tp_name); - return 0; - } -#endif - 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); - auto *newType = reinterpret_cast<SbkObjectType *>(type_new(metatype, args, kwds)); - if (!newType) - return nullptr; - - 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 -#ifndef IS_PY3K - if (PyType_HasFeature(subtype, Py_TPFLAGS_HAVE_GC)) { - subtype->tp_flags &= ~Py_TPFLAGS_HAVE_GC; - subtype->tp_free = PyObject_Del; - } -#endif - auto self = reinterpret_cast<SbkObject *>(MakeSingletonQAppWrapper(subtype)); - return self == nullptr ? nullptr : _setupNew(self, subtype); -} - -void -object_dealloc(PyObject *self) -{ - Py_TYPE(self)->tp_free(self); -} - -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; -} - -} //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; -} - -bool importModule(const char *moduleName, PyTypeObject *** cppApiPtr) -{ - PyObject *sysModules = PyImport_GetModuleDict(); - PyObject *module = PyDict_GetItemString(sysModules, moduleName); - if (!module) { - module = PyImport_ImportModule(moduleName); - if (!module) - return false; - } else { - Py_INCREF(module); - } - - Shiboken::AutoDecRef cppApi(PyObject_GetAttrString(module, "_Cpp_Api")); - Py_DECREF(module); - - if (cppApi.isNull()) - return false; - -#ifdef IS_PY3K - if (PyCapsule_CheckExact(cppApi)) - *cppApiPtr = reinterpret_cast<PyTypeObject **>(PyCapsule_GetPointer(cppApi, nullptr)); -#else - // Python 2.6 doesn't have PyCapsule API, so let's keep usign PyCObject on all Python 2.x - if (PyCObject_Check(cppApi)) - *cppApiPtr = reinterpret_cast<PyTypeObject **>(PyCObject_AsVoidPtr(cppApi)); -#endif - return true; -} - -// 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(); - - PyEval_InitThreads(); - - //Init private data - Pep384_Init(); - - Shiboken::ObjectType::initPrivateData(SbkObject_TypeF()); - - if (PyType_Ready(SbkEnumType_TypeF()) < 0) - Py_FatalError("[libshiboken] Failed to initialise Shiboken.SbkEnumType metatype."); - - if (PyType_Ready(SbkObjectType_TypeF()) < 0) - Py_FatalError("[libshiboken] Failed to initialise Shiboken.BaseWrapperType metatype."); - - if (PyType_Ready(reinterpret_cast<PyTypeObject *>(SbkObject_TypeF())) < 0) - Py_FatalError("[libshiboken] Failed to initialise 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, - const char *signatureStrings[], - ObjectDestructor cppObjDtor, - SbkObjectType *baseType, - PyObject *baseTypes, - unsigned wrapperFlags) -{ - typeSpec->slots[0].pfunc = reinterpret_cast<void *>(baseType ? baseType : SbkObject_TypeF()); - - PyObject *heaptype = PyType_FromSpecWithBases(typeSpec, baseTypes); - Py_TYPE(heaptype) = SbkObjectType_TypeF(); - Py_INCREF(Py_TYPE(heaptype)); - auto *type = reinterpret_cast<SbkObjectType *>(heaptype); - 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); - } - } - // PYSIDE-510: Here is the single change to support signatures. - if (SbkSpecial_Type_Ready(enclosingObject, reinterpret_cast<PyTypeObject *>(type), signatureStrings) < 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); - return PyModule_AddObject(enclosingObject, typeName, ob_type) == 0 ? type : nullptr; -} - -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) -{ - destroy(self, nullptr); -} - -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 7faf223bd..000000000 --- a/sources/shiboken2/libshiboken/basewrapper.h +++ /dev/null @@ -1,468 +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; -}; - - -/// 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 *); - -typedef void *(*ExtendedToCppFunc)(PyObject *); // DEPRECATED. -typedef bool (*ExtendedIsConvertibleFunc)(PyObject *); // DEPRECATED. - -// Used in userdata dealloc function -typedef void (*DeleteUserDataFunc)(void *); - -typedef void (*ObjectDestructor)(void *); - -typedef void (*SubTypeInitHook)(SbkObjectType *, PyObject *, PyObject *); - -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. - */ -LIBSHIBOKEN_API void object_dealloc(PyObject *); -LIBSHIBOKEN_API PyObject *SbkDummyNew(PyTypeObject *type, PyObject *, PyObject *); - -} // 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); -} - -/** - * Shiboken::importModule is DEPRECATED. Use Shiboken::Module::import() instead. - */ -SBK_DEPRECATED(LIBSHIBOKEN_API bool importModule(const char *moduleName, PyTypeObject *** cppApiPtr)); - -// 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, - const char *signatureStrings[], - 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); - -/// \deprecated Use destroy(SbkObject *, void *) -SBK_DEPRECATED(LIBSHIBOKEN_API void destroy(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 56a647b21..000000000 --- a/sources/shiboken2/libshiboken/basewrapper_p.h +++ /dev/null @@ -1,289 +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; - /// True if this type holds two or more C++ instances, e.g.: a Python class which inherits from two C++ classes. - int is_multicpp : 1; - /// True if this type was defined by the user. - 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 - int type_behaviour : 2; - 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 *); -}; - - -} // 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 725150e87..000000000 --- a/sources/shiboken2/libshiboken/bindingmanager.cpp +++ /dev/null @@ -1,355 +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 "basewrapper.h" -#include "basewrapper_p.h" -#include "bindingmanager.h" -#include "sbkdbg.h" -#include "gilstate.h" -#include "sbkstring.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; -} - -PyObject *BindingManager::getOverride(const void *cptr, 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; - - if (wrapper->ob_dict) { - PyObject *method = PyDict_GetItemString(wrapper->ob_dict, methodName); - if (method) { - Py_INCREF(reinterpret_cast<PyObject *>(method)); - return method; - } - } - - PyObject *pyMethodName = Shiboken::String::fromCString(methodName); - 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; - - // 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 i = 1; i < PyTuple_GET_SIZE(mro) - 1; i++) { - auto *parent = reinterpret_cast<PyTypeObject *>(PyTuple_GET_ITEM(mro, i)); - if (parent->tp_dict) { - defaultMethod = PyDict_GetItem(parent->tp_dict, pyMethodName); - if (defaultMethod && PyMethod_GET_FUNCTION(method) != defaultMethod) { - Py_DECREF(pyMethodName); - return method; - } - } - } - } - - Py_XDECREF(method); - Py_DECREF(pyMethodName); - return nullptr; -} - -void BindingManager::addClassInheritance(SbkObjectType *parent, SbkObjectType *child) -{ - m_d->classHierarchy.addEdge(parent, child); -} - -SbkObjectType *BindingManager::resolveType(void *cptr, SbkObjectType *type) -{ - return resolveType(&cptr, type); -} - -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 bfcbdc79b..000000000 --- a/sources/shiboken2/libshiboken/bindingmanager.h +++ /dev/null @@ -1,116 +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, const char *methodName); - - void addClassInheritance(SbkObjectType *parent, SbkObjectType *child); - /** - * \deprecated Use \fn resolveType(void **, SbkObjectType *), this version is broken when used with multiple inheritance - * because the \p cptr pointer of the discovered type may be different of the given \p cptr in case - * of multiple inheritance - */ - SBK_DEPRECATED(SbkObjectType *resolveType(void *cptr, SbkObjectType *type)); - /** - * 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 ddb07390e..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 "pep384impl.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 77aa5c329..000000000 --- a/sources/shiboken2/libshiboken/embed/embedding_generator.py +++ /dev/null @@ -1,242 +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" - flag = '-b' if sys.version_info >= (3,) else '' - 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. - if sys.version_info[0] == 3: - ignore = "backport_inspect.py typing27.py".split() - else: - ignore = "".split() - 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", "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 eb182d8c4..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 'type.__signature__', 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 a59c6f01e..000000000 --- a/sources/shiboken2/libshiboken/gilstate.cpp +++ /dev/null @@ -1,67 +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; - } -} - -} // namespace Shiboken - diff --git a/sources/shiboken2/libshiboken/gilstate.h b/sources/shiboken2/libshiboken/gilstate.h deleted file mode 100644 index d22f688ba..000000000 --- a/sources/shiboken2/libshiboken/gilstate.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 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(); -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 fac72d56f..000000000 --- a/sources/shiboken2/libshiboken/helper.cpp +++ /dev/null @@ -1,169 +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 "helper.h" -#include "sbkstring.h" -#include <stdarg.h> - -#ifdef _WIN32 -# include <windows.h> -#else -# include <pthread.h> -#endif - -namespace Shiboken -{ - -// 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_GetItemString(globals, "__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); -#if _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 14aae8028..000000000 --- a/sources/shiboken2/libshiboken/helper.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 HELPER_H -#define HELPER_H - -#include "sbkpython.h" -#include "shibokenmacros.h" -#include "autodecref.h" - -#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, ...); - -} // 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 fe7157d24..000000000 --- a/sources/shiboken2/libshiboken/pep384impl.cpp +++ /dev/null @@ -1,685 +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 "pep384impl.h" -#include "autodecref.h" - -extern "C" -{ - -/* - * The documentation is located in pep384impl_doc.rst - */ - -/***************************************************************************** - * - * Support for object.h - * - */ - -/* - * Here is the verification code for PyTypeObject. - * We create a type object and check if its fields - * appear at the right offsets. - */ - -#define make_dummy_int(x) (x * sizeof(void *)) -#define make_dummy(x) (reinterpret_cast<void *>(make_dummy_int(x))) - -#ifdef Py_LIMITED_API -datetime_struc *PyDateTimeAPI = NULL; -#endif - -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 */ -}; - -#define probe_tp_call make_dummy(1) -#define probe_tp_str make_dummy(2) -#define probe_tp_traverse make_dummy(3) -#define probe_tp_clear make_dummy(4) -#define probe_tp_methods probe_methoddef -#define probe_tp_getset probe_getseters -#define probe_tp_descr_get make_dummy(7) -#define probe_tp_init make_dummy(8) -#define probe_tp_alloc make_dummy(9) -#define probe_tp_new make_dummy(10) -#define probe_tp_free make_dummy(11) -#define probe_tp_is_gc make_dummy(12) - -#define probe_tp_name "type.probe" -#define probe_tp_basicsize make_dummy_int(42) - -static PyType_Slot typeprobe_slots[] = { - {Py_tp_call, probe_tp_call}, - {Py_tp_str, probe_tp_str}, - {Py_tp_traverse, probe_tp_traverse}, - {Py_tp_clear, probe_tp_clear}, - {Py_tp_methods, probe_tp_methods}, - {Py_tp_getset, probe_tp_getset}, - {Py_tp_descr_get, probe_tp_descr_get}, - {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_GetAttrString(obtype, "__base__")); - PyObject *probe_tp_bases = PyObject_GetAttrString(obtype, "__bases__"); - auto *check = reinterpret_cast<PyTypeObject *>( - PyType_FromSpecWithBases(&typeprobe_spec, probe_tp_bases)); - auto *typetype = reinterpret_cast<PyTypeObject *>(obtype); - PyObject *w = PyObject_GetAttrString(obtype, "__weakrefoffset__"); - long probe_tp_weakrefoffset = PyLong_AsLong(w); - PyObject *d = PyObject_GetAttrString(obtype, "__dictoffset__"); - long probe_tp_dictoffset = PyLong_AsLong(d); - PyObject *probe_tp_mro = PyObject_GetAttrString(obtype, "__mro__"); - if (false - || strcmp(probe_tp_name, check->tp_name) != 0 - || probe_tp_basicsize != check->tp_basicsize - || probe_tp_call != check->tp_call - || 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_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_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_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); -} - - -#ifdef Py_LIMITED_API - -#if PY_VERSION_HEX < PY_ISSUE33738_SOLVED -#include "pep384_issue33738.cpp" -#endif - -/***************************************************************************** - * - * Support for unicodeobject.h - * - */ - -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 = NULL; - if (cstring_dict == NULL) { - cstring_dict = PyDict_New(); - if (cstring_dict == NULL) - Py_FatalError("Error in " AT); - } - PyObject *bytesStr = PyUnicode_AsEncodedString(str, "utf8", NULL); - PyObject *entry = PyDict_GetItem(cstring_dict, bytesStr); - if (entry == NULL) { - 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); -} - -/***************************************************************************** - * - * Support for longobject.h - * - */ - -/* - * 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; -} - -/***************************************************************************** - * - * Support for pydebug.h - * - */ -static PyObject *sys_flags = NULL; - -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 NULL is returned and does not incref. - Py_XINCREF(sys_flags); - initialized = 1; - } - if (sys_flags != NULL) { - PyObject *ob_ret = PyObject_GetAttrString(sys_flags, name); - if (ob_ret != NULL) { - 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; -} - -/***************************************************************************** - * - * Support for code.h - * - */ - -int -PepCode_Get(PyCodeObject *co, const char *name) -{ - PyObject *ob = (PyObject *)co; - PyObject *ob_ret; - int ret = -1; - - ob_ret = PyObject_GetAttrString(ob, name); - if (ob_ret != NULL) { - long long_ret = PyLong_AsLong(ob_ret); - Py_DECREF(ob_ret); - ret = (int) long_ret; - } - return ret; -} - -/***************************************************************************** - * - * Support for datetime.h - * - */ - -static PyTypeObject *dt_getCheck(const char *name) -{ - PyObject *op = PyObject_GetAttrString(PyDateTimeAPI->module, name); - if (op == NULL) { - fprintf(stderr, "datetime.%s not found\n", name); - Py_FatalError("aborting"); - } - return (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 == NULL) - Py_FatalError("PyDateTimeAPI malloc error, aborting"); - PyDateTimeAPI->module = PyImport_ImportModule("datetime"); - if (PyDateTimeAPI->module == NULL) - 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 != NULL) { - 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); -} - -/***************************************************************************** - * - * Support for pythonrun.h - * - */ - -// 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 = NULL; - - if (code != NULL) { - ret = PyEval_EvalCode(code, globals, locals); - } - Py_XDECREF(code); - return ret; -} - -#endif // Py_LIMITED_API - -// This is only a simple local helper that returns a computed variable. -// Used also in Python 2. -#if defined(Py_LIMITED_API) || PY_VERSION_HEX < 0x03000000 -static PyObject * -PepRun_GetResult(const char *command, const char *resvar) -{ - PyObject *d, *v, *res; - - d = PyDict_New(); - if (d == NULL || PyDict_SetItemString(d, "__builtins__", - PyEval_GetBuiltins()) < 0) - return NULL; - v = PyRun_String(command, Py_file_input, d, d); - res = v ? PyDict_GetItemString(d, resvar) : NULL; - Py_XDECREF(v); - Py_DECREF(d); - return res; -} -#endif // Py_LIMITED_API || Python 2 - -#ifdef Py_LIMITED_API - -/***************************************************************************** - * - * Support for classobject.h - * - */ - -PyTypeObject *PepMethod_TypePtr = NULL; - -static PyTypeObject *getMethodType(void) -{ - static const char prog[] = - "class _C:\n" - " def _m(self): pass\n" - "MethodType = type(_C()._m)\n"; - return (PyTypeObject *) PepRun_GetResult(prog, "MethodType"); -} - -// 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_GetAttrString(im, "__func__"); - - // We have to return a borrowed reference. - Py_DECREF(ret); - return ret; -} - -PyObject * -PyMethod_Self(PyObject *im) -{ - PyObject *ret = PyObject_GetAttrString(im, "__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; -} - -/***************************************************************************** - * - * Support for funcobject.h - * - */ - -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 = NULL; - -static PyTypeObject *getFunctionType(void) -{ - static const char prog[] = - "from types import FunctionType\n"; - return (PyTypeObject *) PepRun_GetResult(prog, "FunctionType"); -} - -/***************************************************************************** - * - * Extra support for signature.cpp - * - */ - -PyTypeObject *PepStaticMethod_TypePtr = NULL; - -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" - "StaticMethod_Type = type(spamlist.__dict__['staticmeth'])\n"; - return (PyTypeObject *) PepRun_GetResult(prog, "StaticMethod_Type"); -} - -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 != NULL) { - Py_INCREF(callable); - sm->sm_callable = callable; - } - return (PyObject *)sm; -} -#endif // Py_LIMITED_API - -#if PY_VERSION_HEX < 0x03000000 -PyTypeObject *PepMethodDescr_TypePtr = NULL; - -static PyTypeObject * -getMethodDescrType(void) -{ - static const char prog[] = - "MethodDescr_Type = type(str.split)\n"; - return (PyTypeObject *) PepRun_GetResult(prog, "MethodDescr_Type"); -} -#endif - -/***************************************************************************** - * - * 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; -} - -/***************************************************************************** - * - * 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 - -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 PY_VERSION_HEX < 0X03000000 - const char *namestr = PyString_AsString(name); - if (namestr == NULL || namestr[0] != '_' || namestr[1] != '_') { - Py_INCREF(name); - return name; - } - size_t nlen = strlen(namestr); - /* Don't mangle __id__ or names with dots. */ - if ((namestr[nlen-1] == '_' && namestr[nlen-2] == '_') - || strchr(namestr, '.')) { - Py_INCREF(name); - return name; - } -#else - 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; - } -#endif - Shiboken::AutoDecRef privateobj(PyObject_GetAttrString( - reinterpret_cast<PyObject *>(Py_TYPE(self)), "__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 NULL; - } - 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 // Py_LIMITED_API -} - -/***************************************************************************** - * - * Module Initialization - * - */ - -void -Pep384_Init() -{ - check_PyTypeObject_valid(); -#ifdef Py_LIMITED_API - Pep_GetVerboseFlag(); - PepMethod_TypePtr = getMethodType(); - PepFunction_TypePtr = getFunctionType(); - PepStaticMethod_TypePtr = getStaticMethodType(); -#endif -#if PY_VERSION_HEX < 0x03000000 - PepMethodDescr_TypePtr = getMethodDescrType(); -#endif -} - -} // extern "C" diff --git a/sources/shiboken2/libshiboken/pep384impl.h b/sources/shiboken2/libshiboken/pep384impl.h deleted file mode 100644 index 93f718988..000000000 --- a/sources/shiboken2/libshiboken/pep384impl.h +++ /dev/null @@ -1,499 +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 - -#include "sbkpython.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; - 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; - 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; - -// 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 - -#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 - * - */ -#ifdef Py_LIMITED_API - -LIBSHIBOKEN_API char *_PepUnicode_AsString(PyObject *); - -#if PY_VERSION_HEX < 0x03000000 -#define PyUnicode_GET_SIZE(op) PyUnicode_GetSize((PyObject *)(op)) -#else -// PyUnicode_GetSize is deprecated in favor of PyUnicode_GetLength -#define PyUnicode_GET_SIZE(op) PyUnicode_GetLength((PyObject *)(op)) -#endif - -#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: 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 < 0x0307FFFF) -#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 PyCodeObject; - -LIBSHIBOKEN_API int PepCode_Get(PyCodeObject *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 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 - -/***************************************************************************** - * - * 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 2f3b7ea97..000000000 --- a/sources/shiboken2/libshiboken/pep384impl_doc.rst +++ /dev/null @@ -1,709 +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 redefined to call into ``PyUnicode_GetSize`` -for Python 2, and ``PyUnicode_GetLength`` for Python 3. -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. - - -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 12af9613c..000000000 --- a/sources/shiboken2/libshiboken/qapp_macro.cpp +++ /dev/null @@ -1,256 +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 deleting qApp. -// -static int -qApp_module_index(PyObject *module) -{ - const char *name = PyModule_GetName(module); - int ret = 0; - - if (strcmp(name, "PySide2.QtCore") == 0) - ret = 1; - else if (strcmp(name, "PySide2.QtGui") == 0) - ret = 2; - else if (strcmp(name, "PySide2.QtWidgets") == 0) - ret = 3; - return ret; -} - -#define PYTHON_IS_PYTHON3 (PY_VERSION_HEX >= 0x03000000) -#define PYTHON_IS_PYTHON2 (!PYTHON_IS_PYTHON3) -#define Py_NONE_TYPE Py_TYPE(Py_None) - -#if PYTHON_IS_PYTHON3 -# define BRACE_OPEN { -# define BRACE_CLOSE } -#else -# define BRACE_OPEN -# define BRACE_CLOSE -#endif - -static SbkObject _Py_ChameleonQAppWrapper_Struct = { - BRACE_OPEN - _PyObject_EXTRA_INIT - 1, Py_NONE_TYPE - BRACE_CLOSE -}; - -static PyObject *qApp_var = nullptr; -static PyObject *qApp_content = reinterpret_cast<PyObject *>(&_Py_ChameleonQAppWrapper_Struct); -static PyObject *qApp_moduledicts[5] = {nullptr, nullptr, nullptr, nullptr, nullptr}; -static int qApp_var_ref = 0; -static int qApp_content_ref = 0; - -static int -reset_qApp_var(void) -{ - PyObject **mod_ptr; - - for (mod_ptr = qApp_moduledicts; *mod_ptr != nullptr; mod_ptr++) { - // We respect whatever the user may have set. - PyObject *existing = PyDict_GetItem(*mod_ptr, qApp_var); - if (existing == nullptr || Py_TYPE(existing) == Py_NONE_TYPE) { - if (PyDict_SetItem(*mod_ptr, qApp_var, qApp_content) < 0) - return -1; - } - } - return 0; -} - -/* - * Note: - * The PYSIDE-585 problem was that shutdown is called one more often - * than Q*Application is created. We could special-case that last - * shutdown or add a refcount, initially, but actually it was easier - * and more intuitive in that context to make the refcount of - * qApp_content equal to the refcount of Py_None. - */ -PyObject * -MakeSingletonQAppWrapper(PyTypeObject *type) -{ - if (type == nullptr) - type = Py_NONE_TYPE; - if (!(type == Py_NONE_TYPE || Py_TYPE(qApp_content) == Py_NONE_TYPE)) { - 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; - } - if (reset_qApp_var() < 0) - return nullptr; - // always know the max of the refs - if (Py_REFCNT(qApp_var) > qApp_var_ref) - qApp_var_ref = Py_REFCNT(qApp_var); - if (Py_REFCNT(qApp_content) > qApp_content_ref) - qApp_content_ref = Py_REFCNT(qApp_content); - - if (Py_TYPE(qApp_content) != Py_NONE_TYPE) { - // Remove the "_" variable which might hold a reference to qApp. - Shiboken::AutoDecRef pymain(PyImport_ImportModule("__main__")); - if (pymain.object() && PyObject_HasAttrString(pymain.object(), "_")) - PyObject_DelAttrString(pymain.object(), "_"); - Py_REFCNT(qApp_var) = 1; // fuse is armed... - } - if (type == Py_NONE_TYPE) { - // Debug mode showed that we need to do more than just remove the - // reference. To keep everything in the right order, it is easiest - // to do a full shutdown, using QtCore.__moduleShutdown(). - // restore the "None-state" - PyObject *__moduleShutdown = PyDict_GetItemString(qApp_moduledicts[1], - "__moduleShutdown"); - // PYSIDE-585: It was crucial to update the refcounts *before* - // calling the shutdown. - Py_TYPE(qApp_content) = Py_NONE_TYPE; - Py_REFCNT(qApp_var) = qApp_var_ref; - Py_REFCNT(qApp_content) = Py_REFCNT(Py_None); - if (__moduleShutdown != nullptr) - Py_XDECREF(PyObject_CallFunction(__moduleShutdown, const_cast<char *>("()"))); - } - else - (void)PyObject_INIT(qApp_content, type); - Py_INCREF(qApp_content); - return qApp_content; -} - -#if PYTHON_IS_PYTHON2 - -// Install support in Py_NONE_TYPE for Python 2: 'bool(qApp) == False'. -static int -none_bool(PyObject *v) -{ - return 0; -} - -static PyNumberMethods none_as_number = { - nullptr, /* nb_add */ - nullptr, /* nb_subtract */ - nullptr, /* nb_multiply */ - nullptr, /* nb_divide */ - nullptr, /* nb_remainder */ - nullptr, /* nb_divmod */ - nullptr, /* nb_power */ - nullptr, /* nb_negative */ - nullptr, /* nb_positive */ - nullptr, /* nb_absolute */ - reinterpret_cast<inquiry>(none_bool), /* nb_nonzero */ -}; - -#endif - -static int -setup_qApp_var(PyObject *module) -{ - int module_index; - static int init_done = 0; - - if (!init_done) { -#if PYTHON_IS_PYTHON2 - Py_NONE_TYPE->tp_as_number = &none_as_number; -#endif - qApp_var = Py_BuildValue("s", "qApp"); - if (qApp_var == nullptr) - return -1; - // This is a borrowed reference - qApp_moduledicts[0] = PyEval_GetBuiltins(); - Py_INCREF(qApp_moduledicts[0]); - init_done = 1; - } - - // Initialize qApp. We insert it into __dict__ for "import *" and also - // into __builtins__, to let it appear like a real macro. - module_index = qApp_module_index(module); - if (module_index) { - // This line gets a borrowed reference - qApp_moduledicts[module_index] = PyModule_GetDict(module); - Py_INCREF(qApp_moduledicts[module_index]); - if (reset_qApp_var() < 0) - return -1; - } - return 0; -} - -void -NotifyModuleForQApp(PyObject *module, void *qApp) -{ - setup_qApp_var(module); - /* - * PYSIDE-571: Check if an QApplication instance exists before the import. - * This happens in scriptableapplication and application_test.py . - * - * Crucial Observation - * =================== - * - * A Q*Application object from C++ does not have a wrapper or constructor - * like instances created by Python. It makes no sense to support - * deletion or special features like qApp resurrection. - * - * Therefore, the implementation is very simple and just redirects the - * qApp_contents variable and assigns the instance, instead of vice-versa. - */ - PyObject *coreDict = qApp_moduledicts[1]; - if (qApp != nullptr && coreDict != nullptr) { - PyObject *coreApp = PyDict_GetItemString(coreDict, "QCoreApplication"); - if (coreApp != nullptr) { - qApp_content = PyObject_CallMethod(coreApp, "instance", ""); - reset_qApp_var(); - } - } -} - - -} //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 be45241de..000000000 --- a/sources/shiboken2/libshiboken/qapp_macro.h +++ /dev/null @@ -1,53 +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 *MakeSingletonQAppWrapper(PyTypeObject *type); -LIBSHIBOKEN_API void NotifyModuleForQApp(PyObject *module, void *qApp); - -} // 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 071870780..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 (typespec.cpp, typespec.h, 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 fd09efdae..000000000 --- a/sources/shiboken2/libshiboken/sbkarrayconverter.cpp +++ /dev/null @@ -1,289 +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) -{ -#ifdef IS_PY3K - return PyLong_Check(pyIn); -#else - return PyInt_Check(pyIn); -#endif -} - -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 d87162071..000000000 --- a/sources/shiboken2/libshiboken/sbkconverter_p.h +++ /dev/null @@ -1,575 +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 PY_MAJOR_VERSION >= 3 - 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"); - } -#else - if (PyInt_Check(pyIn)) { - long result = PyInt_AsLong(pyIn); - if (OverFlowChecker<unsigned PY_LONG_LONG>::check(result, pyIn)) - PyErr_SetObject(PyExc_OverflowError, 0); - *reinterpret_cast<unsigned PY_LONG_LONG * >(cppOut) = - static_cast<unsigned PY_LONG_LONG>(result); - } else 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, 0); - *reinterpret_cast<unsigned PY_LONG_LONG * >(cppOut) = result; - } else { - PyErr_SetString(PyExc_TypeError, "Invalid type for unsigned long long conversion"); - } -#endif // Python 2 - } - 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 02ea773ac..000000000 --- a/sources/shiboken2/libshiboken/sbkdbg.h +++ /dev/null @@ -1,129 +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) { -#ifdef IS_PY3K - PyObject *str = PyUnicode_AsUTF8String(repr); - Py_DECREF(repr); - repr = str; -#endif - 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 71fcf5f64..000000000 --- a/sources/shiboken2/libshiboken/sbkenum.cpp +++ /dev/null @@ -1,669 +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 "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; - PyObject *item = Shiboken::Enum::getEnumItemFromValue(type, itemValue); - if (item) { - self->ob_name = SbkEnumObject_name(item, nullptr); - Py_XDECREF(item); - } else { - self->ob_name = nullptr; - } - return reinterpret_cast<PyObject *>(self); -} - -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); -} - -#ifndef IS_PY3K -static PyObject *enum_divide(PyObject *self, PyObject *v) -{ - return enum_op(PyNumber_Divide, self, v); -} -#endif - -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 -}; - -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}, -#ifndef IS_PY3K - {Py_nb_divide, (void *)enum_divide}, -#endif - {Py_nb_positive, (void *)enum_int}, -#ifdef IS_PY3K - {Py_nb_bool, (void *)enum_bool}, -#else - {Py_nb_nonzero, (void *)enum_bool}, - {Py_nb_long, (void *)enum_int}, -#endif - {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}, - {0, nullptr} -}; -static PyType_Spec SbkEnumType_Type_spec = { - "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 = (PyTypeObject *)PyType_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 -} - -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" - -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_GetItemString(enumType->tp_dict, const_cast<char *>("values")); - - while (PyDict_Next(values, &pos, &key, &value)) { - auto *obj = reinterpret_cast<SbkEnumObject *>(value); - if (obj->ob_value == itemValue) { - Py_INCREF(obj); - 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) - 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) - return nullptr; - if (flagsType && PyModule_AddObject(module, PepType_GetNameStr(flagsType), - reinterpret_cast<PyObject *>(flagsType)) < 0) - 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) - return nullptr; - if (flagsType && PyDict_SetItemString(reinterpret_cast<PyTypeObject *>(scope)->tp_dict, - PepType_GetNameStr(flagsType), - reinterpret_cast<PyObject *>(flagsType)) < 0) - 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) - return nullptr; - Py_DECREF(enumItem); - return enumItem; -} - -bool createGlobalEnumItem(PyTypeObject *enumType, PyObject *module, const char *itemName, long itemValue) -{ - PyObject *enumItem = createEnumItem(enumType, itemName, itemValue); - if (enumItem) { - if (PyModule_AddObject(module, itemName, enumItem) < 0) - return false; - // @TODO This Py_DECREF causes crashes on exit with a debug Python interpreter, essentially - // causing a use-after-free in the GC. This is now commented out to cause a memory leak - // instead of a crash. Proper memory management of Enum types and items should be - // implemented. See PYSIDE-488. This will require proper allocation and deallocation of - // the underlying Enum PyHeapType, which is currently just deallocated at application exit. - // Py_DECREF(enumItem); - return true; - } - return false; -} - -bool createScopedEnumItem(PyTypeObject *enumType, PyTypeObject *scope, - const char *itemName, long itemValue) -{ - if (PyObject *enumItem = createEnumItem(enumType, itemName, itemValue)) { - if (PyDict_SetItemString(reinterpret_cast<PyTypeObject *>(scope)->tp_dict, itemName, enumItem) < 0) - return false; - Py_DECREF(enumItem); - return true; - } - return false; -} - -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) { - PyObject *values = PyDict_GetItemString(enumType->tp_dict, const_cast<char *>("values")); - if (!values) { - values = PyDict_New(); - PyDict_SetItemString(enumType->tp_dict, const_cast<char *>("values"), values); - Py_DECREF(values); // ^ values still alive, because setitemstring incref it - } - 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_new, (void *)SbkEnum_tp_new}, - {Py_nb_add, (void *)enum_add}, - {Py_nb_subtract, (void *)enum_subtract}, - {Py_nb_multiply, (void *)enum_multiply}, -#ifndef IS_PY3K - {Py_nb_divide, (void *)enum_divide}, -#endif - {Py_nb_positive, (void *)enum_int}, -#ifdef IS_PY3K - {Py_nb_bool, (void *)enum_bool}, -#else - {Py_nb_nonzero, (void *)enum_bool}, - {Py_nb_long, (void *)enum_int}, -#endif - {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 *)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); -#ifdef IS_PY3K - PUT_SLOT(Py_nb_bool); -#else - PUT_SLOT(Py_nb_nonzero); -#endif - 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); -#ifndef IS_PY3K - PUT_SLOT(Py_nb_long); - PUT_SLOT(Py_nb_divide); -#endif -#undef PUT_SLOT - *pidx = idx; -} - -PyTypeObject * -newTypeWithName(const char *name, - const char *cppName, - PyTypeObject *numbers_fromFlag) -{ - // Careful: PyType_FromSpec does not allocate the string. - PyType_Slot newslots[99] = {}; // enough but not too big for the stack - auto *newspec = new PyType_Spec; - 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 *>(PyType_FromSpec(newspec)); - Py_TYPE(type) = SbkEnumType_TypeF(); - Py_INCREF(Py_TYPE(type)); - - 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 'PyType_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 759d72636..000000000 --- a/sources/shiboken2/libshiboken/sbkenum.h +++ /dev/null @@ -1,121 +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); -} - -} // 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 9321725d6..000000000 --- a/sources/shiboken2/libshiboken/sbkmodule.cpp +++ /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$ -** -****************************************************************************/ - -#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(); -#ifndef IS_PY3K - return Py_InitModule(moduleName, reinterpret_cast<PyMethodDef *>(moduleData)); -#else - return PyModule_Create(reinterpret_cast<PyModuleDef *>(moduleData)); -#endif -} - -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 75eff5a79..000000000 --- a/sources/shiboken2/libshiboken/sbkmodule.h +++ /dev/null @@ -1,115 +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" - -#if PY_MAJOR_VERSION >= 3 - #define SBK_MODULE_INIT_ERROR 0 - #define SBK_MODULE_INIT_FUNCTION_BEGIN(ModuleName) \ - extern "C" SBK_EXPORT_MODULE PyObject *PyInit_##ModuleName() { - - #define SBK_MODULE_INIT_FUNCTION_END \ - return module; } -#else - #define SBK_MODULE_INIT_ERROR - #define SBK_MODULE_INIT_FUNCTION_BEGIN(ModuleName) \ - extern "C" SBK_EXPORT_MODULE void init##ModuleName() { - - #define SBK_MODULE_INIT_FUNCTION_END \ - } -#endif - -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 f06b0b19e..000000000 --- a/sources/shiboken2/libshiboken/sbkpython.h +++ /dev/null @@ -1,142 +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" - -// 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" -# include "pep384impl.h" -# include "typespec.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" -# include "pep384impl.h" -# include "typespec.h" -#endif - -#if PY_MAJOR_VERSION >= 3 - #define IS_PY3K - - #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) - -#else - // Note: if there wasn't for the old-style classes, only a PyNumber_Check would suffice. - #define SbkNumber_Check(X) \ - (PyNumber_Check(X) && (!PyInstance_Check(X) || PyObject_HasAttrString(X, "__trunc__"))) - #define SBK_NB_BOOL(x) (x).nb_nonzero - #define SBK_PyMethod_New(X, Y) PyMethod_New(X, Y, reinterpret_cast<PyObject *>(Py_TYPE(Y))) - - #define Py_hash_t long -#endif - -#endif diff --git a/sources/shiboken2/libshiboken/sbkstring.cpp b/sources/shiboken2/libshiboken/sbkstring.cpp deleted file mode 100644 index 9ba5be281..000000000 --- a/sources/shiboken2/libshiboken/sbkstring.cpp +++ /dev/null @@ -1,205 +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 "sbkstring.h" -#include "autodecref.h" - -namespace Shiboken -{ - -namespace String -{ - -bool checkType(PyTypeObject *type) -{ - return type == &PyUnicode_Type -#if PY_MAJOR_VERSION < 3 - || type == &PyString_Type -#endif - ; -} - -bool check(PyObject *obj) -{ - return obj == Py_None || -#if PY_MAJOR_VERSION < 3 - PyString_Check(obj) || -#endif - 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) -{ -#ifdef IS_PY3K - return PyUnicode_FromString(value); -#else - return PyBytes_FromString(value); -#endif -} - -PyObject *fromCString(const char *value, int len) -{ -#ifdef IS_PY3K - return PyUnicode_FromStringAndSize(value, len); -#else - return PyBytes_FromStringAndSize(value, len); -#endif -} - -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()); - } -#ifdef IS_PY3K - // Return unicode from str instead of uniStr, because the lifetime of the returned pointer - // depends on the lifetime of str. - return _PepUnicode_AsString(str); -#else - str = PyUnicode_AsUTF8String(str); - if (str == NULL) { - return NULL; - } - return PyString_AsString(str); -#endif - } - 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; - } - -#if PY_MAJOR_VERSION < 3 - if (PyString_Check(*val1) && PyString_Check(val2)) { - PyString_Concat(val1, val2); - return true; - } -#endif - return false; -} - -PyObject *fromFormat(const char *format, ...) -{ - va_list argp; - va_start(argp, format); - PyObject *result = nullptr; -#ifdef IS_PY3K - result = PyUnicode_FromFormatV(format, argp); -#else - result = PyString_FromFormatV(format, argp); -#endif - va_end(argp); - return result; -} - -PyObject *fromStringAndSize(const char *str, Py_ssize_t size) -{ -#ifdef IS_PY3K - return PyUnicode_FromStringAndSize(str, size); -#else - return PyString_FromStringAndSize(str, size); -#endif -} - -int compare(PyObject *val1, const char *val2) -{ - if (PyUnicode_Check(val1)) -#ifdef IS_PY3K - return PyUnicode_CompareWithASCIIString(val1, val2); -#else - { - PyObject *uVal2 = PyUnicode_FromString(val2); - bool result = PyUnicode_Compare(val1, uVal2); - Py_XDECREF(uVal2); - return result; - } - if (PyString_Check(val1)) - return strcmp(PyString_AS_STRING(val1), val2); -#endif - return 0; - -} - -Py_ssize_t len(PyObject *str) -{ - if (str == Py_None) - return 0; - - if (PyUnicode_Check(str)) - return PyUnicode_GET_SIZE(str); - - if (PyBytes_Check(str)) - return PyBytes_GET_SIZE(str); - return 0; -} - -} // namespace String - -} // namespace Shiboken diff --git a/sources/shiboken2/libshiboken/sbkstring.h b/sources/shiboken2/libshiboken/sbkstring.h deleted file mode 100644 index 7f434e1b9..000000000 --- a/sources/shiboken2/libshiboken/sbkstring.h +++ /dev/null @@ -1,75 +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 SBKSTRING_H -#define SBKSTRING_H - -#include "sbkpython.h" -#include "shibokenmacros.h" - -#if PY_MAJOR_VERSION >= 3 - #define SBK_BYTES_NAME "bytes" -#else - #define SBK_BYTES_NAME "str" -#endif - -namespace Shiboken -{ -namespace String -{ - LIBSHIBOKEN_API bool check(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); - -} // 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 1356670aa..000000000 --- a/sources/shiboken2/libshiboken/shiboken.h +++ /dev/null @@ -1,59 +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 "shibokenmacros.h" -#include "shibokenbuffer.h" - -#endif // SHIBOKEN_H - diff --git a/sources/shiboken2/libshiboken/shibokenbuffer.cpp b/sources/shiboken2/libshiboken/shibokenbuffer.cpp deleted file mode 100644 index 330470183..000000000 --- a/sources/shiboken2/libshiboken/shibokenbuffer.cpp +++ /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$ -** -****************************************************************************/ - -#include "shibokenbuffer.h" -#include <cstdlib> -#include <cstring> - -bool Shiboken::Buffer::checkType(PyObject *pyObj) -{ - return PyObject_CheckReadBuffer(pyObj) != 0; -} - -void *Shiboken::Buffer::getPointer(PyObject *pyObj, Py_ssize_t *size) -{ - const void *buffer = nullptr; -#ifdef IS_PY3K - Py_buffer view; - if (PyObject_GetBuffer(pyObj, &view, PyBUF_ND) == 0) { - if (size) - *size = view.len; - buffer = view.buf; - PyBuffer_Release(&view); - return view.buf; - } - return nullptr; -#else - Py_ssize_t bufferSize = 0; - - PyObject_AsReadBuffer(pyObj, &buffer, &bufferSize); - - if (size) - *size = bufferSize; -#endif - return const_cast<void *>(buffer); -} - -PyObject *Shiboken::Buffer::newObject(void *memory, Py_ssize_t size, Type type) -{ - if (size == 0) - Py_RETURN_NONE; -#ifdef IS_PY3K - 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); -#else - return type == ReadOnly ? PyBuffer_FromMemory(memory, size) : PyBuffer_FromReadWriteMemory(memory, size); -#endif -} - -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 7bebd85e4..000000000 --- a/sources/shiboken2/libshiboken/shibokenmacros.h +++ /dev/null @@ -1,63 +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 SHIBOKENMACROS_H -#define SHIBOKENMACROS_H - -// LIBSHIBOKEN_API macro is used for the public API symbols. -#if defined _WIN32 - #if LIBSHIBOKEN_EXPORTS - #define LIBSHIBOKEN_API __declspec(dllexport) - #else - #ifdef _MSC_VER - #define LIBSHIBOKEN_API __declspec(dllimport) - #endif - #endif - #define SBK_DEPRECATED(func) __declspec(deprecated) func -#elif __GNUC__ >= 4 - #define LIBSHIBOKEN_API __attribute__ ((visibility("default"))) - #define SBK_DEPRECATED(func) func __attribute__ ((deprecated)) -#endif - -#ifndef LIBSHIBOKEN_API - #define LIBSHIBOKEN_API - #define SBK_DEPRECATED(func) func -#endif - -#endif diff --git a/sources/shiboken2/libshiboken/signature.cpp b/sources/shiboken2/libshiboken/signature.cpp deleted file mode 100644 index e62f861a2..000000000 --- a/sources/shiboken2/libshiboken/signature.cpp +++ /dev/null @@ -1,1203 +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 "basewrapper.h" -#include "autodecref.h" - -extern "C" -{ - -/* - * The documentation is located in file signature_doc.rst - */ -#include "signature.h" -#include <structmember.h> - -// These constants were needed in former versions of the module: -#define PYTHON_HAS_QUALNAME (PY_VERSION_HEX >= 0x03030000) -#define PYTHON_HAS_UNICODE (PY_VERSION_HEX >= 0x03000000) -#define PYTHON_HAS_WEAKREF_PYCFUNCTION (PY_VERSION_HEX >= 0x030500A0) -#define PYTHON_IS_PYTHON3 (PY_VERSION_HEX >= 0x03000000) -#define PYTHON_HAS_KEYWORDONLY (PYTHON_IS_PYTHON3) -#define PYTHON_USES_PERCENT_V_FORMAT (PYTHON_IS_PYTHON3) -#define PYTHON_HAS_DESCR_REDUCE (PY_VERSION_HEX >= 0x03040000) -#define PYTHON_HAS_METH_REDUCE (PYTHON_HAS_DESCR_REDUCE) -#define PYTHON_NEEDS_ITERATOR_FLAG (!PYTHON_IS_PYTHON3) -#define PYTHON_EXPOSES_METHODDESCR (PYTHON_IS_PYTHON3) -#define PYTHON_NO_TYPE_IN_FUNCTIONS (!PYTHON_IS_PYTHON3 || Py_LIMITED_API) -#define PYTHON_HAS_INT_AND_LONG (!PYTHON_IS_PYTHON3) - -// These constants are still in use: -#define PYTHON_USES_D_COMMON (PY_VERSION_HEX >= 0x03020000) - -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 - // init part 2: run module - PyObject *pyside_type_init_func; - PyObject *create_signature_func; - PyObject *seterror_argument_func; - PyObject *make_helptext_func; -} safe_globals_struc, *safe_globals; - -static safe_globals pyside_globals = nullptr; - -static PyObject *GetTypeKey(PyObject *ob); - -static PyObject *GetSignature_Function(PyObject *, const char *); -static PyObject *GetSignature_TypeMod(PyObject *, const char *); -static PyObject *GetSignature_Wrapper(PyObject *, const char *); -static PyObject *get_signature(PyObject *self, PyObject *args); -static PyObject *get_signature_intern(PyObject *ob, const char *modifier); - -static PyObject *PySide_BuildSignatureProps(PyObject *class_mod); - -static void init_module_1(void); -static void init_module_2(void); - -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 for a dummy-function. - * 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); -} - -typedef PyObject *(*signaturefunc)(PyObject *, const char *); - -static PyObject * -_get_written_signature(signaturefunc sf, PyObject *ob, const char *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; -} - -static PyObject * -pyside_cf_get___signature__(PyObject *func, const char *modifier) -{ - init_module_2(); - return _get_written_signature(GetSignature_Function, func, modifier); -} - -static PyObject * -pyside_sm_get___signature__(PyObject *sm, const char *modifier) -{ - init_module_2(); - Shiboken::AutoDecRef func(PyObject_GetAttrString(sm, "__func__")); - if (Py_TYPE(func) == PepFunction_TypePtr) - return PyObject_GetAttrString(func, "__signature__"); - return _get_written_signature(GetSignature_Function, func, modifier); -} - -static 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. - Shiboken::AutoDecRef special(Py_BuildValue("(Os)", ob_cf, "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; -} - -static PyObject * -_get_class_of_sm(PyObject *ob_sm) -{ - Shiboken::AutoDecRef func(PyObject_GetAttrString(ob_sm, "__func__")); - return _get_class_of_cf(func); -} - -static PyObject * -_get_class_of_descr(PyObject *ob) -{ - Shiboken::AutoDecRef func_name(PyObject_GetAttrString(ob, "__name__")); - return PyObject_GetAttrString(ob, "__objclass__"); -} - -static PyObject * -GetClassOfFunc(PyObject *ob) -{ - 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 GetClassOfFunc"); - return nullptr; -} - -static PyObject * -get_funcname(PyObject *ob) -{ - PyObject *func = ob; - if (Py_TYPE(ob) == PepStaticMethod_TypePtr) - func = PyObject_GetAttrString(ob, "__func__"); - else - Py_INCREF(func); - PyObject *func_name = PyObject_GetAttrString(func, "__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); - Shiboken::AutoDecRef func_name(get_funcname(ob)); - Shiboken::AutoDecRef type_key(GetTypeKey(GetClassOfFunc(ob))); - return Py_BuildValue("(OO)", type_key.object(), func_name.object()); -} - -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; - - Shiboken::AutoDecRef type_key(GetTypeKey(obtype)); - for (; meth->ml_name != nullptr; meth++) { - Shiboken::AutoDecRef func(PyCFunction_NewEx(meth, obtype, nullptr)); - Shiboken::AutoDecRef func_name(get_funcname(func)); - Shiboken::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; -} - -static 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. - */ - Shiboken::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 - Shiboken::AutoDecRef type_key(GetTypeKey(GetClassOfFunc(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 * -pyside_md_get___signature__(PyObject *ob_md, const char *modifier) -{ - init_module_2(); - Shiboken::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); -} - -static PyObject * -pyside_wd_get___signature__(PyObject *ob, const char *modifier) -{ - init_module_2(); - return _get_written_signature(GetSignature_Wrapper, ob, modifier); -} - -static PyObject * -pyside_tp_get___signature__(PyObject *obtype_mod, const char *modifier) -{ - init_module_2(); - return _get_written_signature(GetSignature_TypeMod, obtype_mod, modifier); -} - -// forward -static PyObject * -GetSignature_Cached(PyObject *props, const char *sig_kind, const char *modifier); - -static PyObject * -GetTypeKey(PyObject *ob) -{ - assert(PyType_Check(ob) || PyModule_Check(ob)); - /* - * We obtain a unique key using the module name and the type name. - * - * The type name is a bit funny when modules are nested. - * Example: - * - * "sample.Photon.ValueIdentity" is a class. - * name: "ValueIdentity" - * module: "sample.Photon" - * - * This is the PyCFunction behavior, as opposed to Python functions. - */ - Shiboken::AutoDecRef class_name(PyObject_GetAttrString(ob, "__name__")); - Shiboken::AutoDecRef module_name(PyObject_GetAttrString(ob, "__module__")); - - if (module_name.isNull()) - PyErr_Clear(); - - // Note: if we have a module, then __module__ is null, and we get - // the module name through __name__ . - if (class_name.isNull()) - return nullptr; - if (module_name.object()) - return Py_BuildValue("(OO)", module_name.object(), class_name.object()); - return Py_BuildValue("O", class_name.object()); -} - -static PyObject *empty_dict = nullptr; - -static 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_Function(PyObject *obfunc, const char *modifier) -{ - // make sure that we look into PyCFunction, only... - if (Py_TYPE(obfunc) == PepFunction_TypePtr) - Py_RETURN_NONE; - Shiboken::AutoDecRef obtype_mod(GetClassOfFunc(obfunc)); - Shiboken::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; - Shiboken::AutoDecRef func_name(PyObject_GetAttrString(obfunc, "__name__")); - PyObject *props = !func_name.isNull() ? PyDict_GetItem(dict, func_name) : nullptr; - if (props == nullptr) - Py_RETURN_NONE; - - int flags = PyCFunction_GET_FLAGS(obfunc); - const char *sig_kind; - if (PyModule_Check(obtype_mod)) - sig_kind = "function"; - else if (flags & METH_CLASS) - sig_kind = "classmethod"; - else if (flags & METH_STATIC) - sig_kind = "staticmethod"; - else - sig_kind = "method"; - return GetSignature_Cached(props, sig_kind, modifier); -} - -static PyObject * -GetSignature_Wrapper(PyObject *ob, const char *modifier) -{ - Shiboken::AutoDecRef func_name(PyObject_GetAttrString(ob, "__name__")); - Shiboken::AutoDecRef objclass(PyObject_GetAttrString(ob, "__objclass__")); - Shiboken::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, "method", modifier); -} - -static PyObject * -GetSignature_TypeMod(PyObject *ob, const char *modifier) -{ - Shiboken::AutoDecRef ob_name(PyObject_GetAttrString(ob, "__name__")); - Shiboken::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, "method", modifier); -} - -static PyObject * -GetSignature_Cached(PyObject *props, const char *sig_kind, const char *modifier) -{ - Shiboken::AutoDecRef key(modifier == nullptr - ? Py_BuildValue("s", sig_kind) - : Py_BuildValue("(ss)", sig_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; -} - -static const char *PySide_CompressedSignaturePackage[] = { -#include "embed/signature.inc" - }; - -static const unsigned char PySide_SignatureLoader[] = { -#include "embed/signature_bootstrap.inc" - }; - -static safe_globals_struc * -init_phase_1(void) -{ - { - 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 - Shiboken::AutoDecRef marshal_str(Py_BuildValue("s", "marshal")); - if (marshal_str.isNull()) - goto error; - Shiboken::AutoDecRef marshal_module(PyImport_Import(marshal_str)); - if (marshal_module.isNull()) - goto error; - Shiboken::AutoDecRef loads(PyObject_GetAttrString(marshal_module, "loads")); - if (loads.isNull()) - goto error; -#endif - char *bytes_cast = reinterpret_cast<char *>( - const_cast<unsigned char *>(PySide_SignatureLoader)); - Shiboken::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_GetItemString(builtins, "compile"); - if (compile == nullptr) - goto error; - Shiboken::AutoDecRef code_obj(PyObject_CallFunction(compile, "Oss", - bytes.object(), "(builtin)", "exec")); -#else - Shiboken::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_SetItemString(mdict, "__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; - - return p; - } -error: - PyErr_Print(); - PyErr_SetString(PyExc_SystemError, "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; - return 0; - } -error: - PyErr_Print(); - PyErr_SetString(PyExc_SystemError, "could not initialize part 2"); - return -1; -} - -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 - } - } - } - // staticmethod has just a __doc__ in the class - assert(strcmp(type->tp_name, "staticmethod") == 0); - return 0; -} - -static int -add_more_getsets(PyTypeObject *type, PyGetSetDef *gsp, PyObject **old_descr) -{ - /* - * This function is used to assign a new __signature__ attribute, - * and also to override a __doc__ 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) { - assert(strcmp(gsp->name, "__doc__") == 0); - Py_INCREF(have_descr); - *old_descr = have_descr; - if (!_fixup_getset(type, gsp->name, gsp)) - continue; - } - Shiboken::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; -} - -//////////////////////////////////////////////////////////////////////////// -// -// 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(); - Shiboken::AutoDecRef ob_type(GetClassOfFunc(ob)); - auto *type = reinterpret_cast<PyTypeObject *>(ob_type.object()); - if (handle_doc_in_progress || strncmp(type->tp_name, "PySide2.", 8) != 0) - return PyObject_CallMethod(old_descr, const_cast<char *>("__get__"), const_cast<char *>("(O)"), ob); - 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); -} - -static 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. - if (get_signature_intern(op, nullptr)) { - 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} -}; - -//////////////////////////////////////////////////////////////////////////// -// -// get_signature -- providing a superior interface -// -// Additionally 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. -// - -static PyObject * -get_signature_intern(PyObject *ob, const char *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; - const char *modifier = nullptr; - - init_module_1(); - - if (!PyArg_ParseTuple(args, "O|s", &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; -} - -//////////////////////////////////////////////////////////////////////////// -// -// This special Type_Ready does certain initializations earlier with -// our new version. -// - -#ifndef _WIN32 -//////////////////////////////////////////////////////////////////////////// -// a stack trace for linux-like platforms -#include <stdio.h> -#include <execinfo.h> -#include <signal.h> -#include <stdlib.h> -#include <unistd.h> - -void handler(int sig) { - 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 - fprintf(stderr, "Error: signal %d:\n", sig); - backtrace_symbols_fd(array, size, STDERR_FILENO); - exit(1); -} - -//////////////////////////////////////////////////////////////////////////// -#endif // _WIN32 - -static int -PySide_PatchTypes(void) -{ - static int init_done = 0; - - if (!init_done) { - Shiboken::AutoDecRef meth_descr(PyObject_GetAttrString( - reinterpret_cast<PyObject *>(&PyString_Type), "split")); - Shiboken::AutoDecRef wrap_descr(PyObject_GetAttrString( - reinterpret_cast<PyObject *>(Py_TYPE(Py_True)), "__add__")); - if (meth_descr.isNull() || wrap_descr.isNull() - || PyType_Ready(Py_TYPE(meth_descr)) < 0 - || add_more_getsets(PepMethodDescr_TypePtr, new_PyMethodDescr_getsets, &old_md_doc_descr) < 0 - || add_more_getsets(&PyCFunction_Type, new_PyCFunction_getsets, &old_cf_doc_descr) < 0 - || add_more_getsets(PepStaticMethod_TypePtr, new_PyStaticMethod_getsets, &old_sm_doc_descr) < 0 - || add_more_getsets(&PyType_Type, new_PyType_getsets, &old_tp_doc_descr) < 0 - || add_more_getsets(Py_TYPE(wrap_descr), new_PyWrapperDescr_getsets, &old_wd_doc_descr) < 0 - ) - return -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 - init_done = 1; - } - return 0; -} - -static void -init_module_1(void) -{ - static int init_done = 0; - - if (!init_done) { - pyside_globals = init_phase_1(); - if (pyside_globals != nullptr) - init_done = 1; - } -} - -static int -PySide_BuildSignatureArgs(PyObject *obtype_mod, const char *signatures[]) -{ - init_module_1(); - Shiboken::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. - */ - Shiboken::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; -} - -static PyMethodDef signature_methods[] = { - {"get_signature", (PyCFunction)get_signature, METH_VARARGS, - "get the __signature__, but pass an optional string parameter"}, - {nullptr, nullptr} -}; - -static 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); - } -} - -static PyObject * -_address_to_stringlist(PyObject *numkey) -{ - 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; - Shiboken::AutoDecRef pystr(Py_BuildValue("s", sig_str)); - if (pystr.isNull() || PyList_Append(res_list, pystr) < 0) - return nullptr; - } - return res_list; -} - -static 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); - Shiboken::AutoDecRef strings(_address_to_stringlist(numkey)); - if (strings.isNull()) - return nullptr; - Shiboken::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; - } - // 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 _finish_nested_classes(PyObject *dict); -static int _build_func_to_type(PyObject *obtype); - -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 too early. - * - * 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; - return 0; -} - -static 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; -} - -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); - const char *look_attr = meth->ml_flags & METH_STATIC ? "__func__" : "__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. - Shiboken::AutoDecRef look(PyObject_GetAttrString(descr, look_attr)); - Shiboken::AutoDecRef given(Py_BuildValue("s", meth->ml_name)); - if (look.isNull() - || (check_name && PyObject_RichCompareBool(look, given, Py_EQ) != 1)) { - PyErr_Clear(); - Shiboken::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. - Shiboken::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 -SbkSpecial_Type_Ready(PyObject * /* module */, PyTypeObject *type, - const char *signatures[]) -{ - if (PyType_Ready(type) < 0) - return -1; - 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! - */ - PySide_PatchTypes(); - if (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(); - Shiboken::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, const char *modifier) -{ - return pyside_tp_get___signature__(ob, modifier); -} - -PyObject *Sbk_TypeGet___doc__(PyObject *ob) -{ - return pyside_tp_get___doc__(ob); -} - -} //extern "C" diff --git a/sources/shiboken2/libshiboken/signature.h b/sources/shiboken2/libshiboken/signature.h deleted file mode 100644 index 57fd4047a..000000000 --- a/sources/shiboken2/libshiboken/signature.h +++ /dev/null @@ -1,56 +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 - -#include "sbkpython.h" - -extern "C" -{ - -LIBSHIBOKEN_API int SbkSpecial_Type_Ready(PyObject *, 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 *, const char *); -LIBSHIBOKEN_API PyObject *Sbk_TypeGet___doc__(PyObject *); - -} // extern "C" - -#endif // SIGNATURE_H diff --git a/sources/shiboken2/libshiboken/signature_doc.rst b/sources/shiboken2/libshiboken/signature_doc.rst deleted file mode 100644 index 9c42c5976..000000000 --- a/sources/shiboken2/libshiboken/signature_doc.rst +++ /dev/null @@ -1,348 +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 4 seconds) to run througs every single signature -object, since these are more than 15000 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 - python_minilib_2_7.py - python_minilib_3_5.py - python_minilib_3_6.py - python_minilib_3_7.py - - signature/ - loader.py - parser.py - mapping.py - errorhandler.py - layout.py - - lib/ - enum_sig.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. - - -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/threadstatesaver.cpp b/sources/shiboken2/libshiboken/threadstatesaver.cpp deleted file mode 100644 index 0d19528f9..000000000 --- a/sources/shiboken2/libshiboken/threadstatesaver.cpp +++ /dev/null @@ -1,67 +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 (PyEval_ThreadsInitialized()) - 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/typespec.cpp b/sources/shiboken2/libshiboken/typespec.cpp deleted file mode 100644 index 6dc5b00bc..000000000 --- a/sources/shiboken2/libshiboken/typespec.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 "sbkpython.h" -#include "typespec.h" -#include <structmember.h> - -#if PY_MAJOR_VERSION < 3 - -extern "C" -{ - -// for some reason python 2.7 needs this on Windows -#ifdef WIN32 -static PyGC_Head *_PyGC_generation0; -#endif - -// from pymacro.h -#ifndef Py_PYMACRO_H -#define Py_PYMACRO_H - -/* Minimum value between x and y */ -#define Py_MIN(x, y) (((x) > (y)) ? (y) : (x)) - -/* Maximum value between x and y */ -#define Py_MAX(x, y) (((x) > (y)) ? (x) : (y)) - -/* Absolute value of the number x */ -#define Py_ABS(x) ((x) < 0 ? -(x) : (x)) - -#define _Py_XSTRINGIFY(x) #x - -/* Convert the argument to a string. For example, Py_STRINGIFY(123) is replaced - with "123" by the preprocessor. Defines are also replaced by their value. - For example Py_STRINGIFY(__LINE__) is replaced by the line number, not - by "__LINE__". */ -#define Py_STRINGIFY(x) _Py_XSTRINGIFY(x) - -/* Get the size of a structure member in bytes */ -#define Py_MEMBER_SIZE(type, member) sizeof(((type *)0)->member) - -/* Argument must be a char or an int in [-128, 127] or [0, 255]. */ -#define Py_CHARMASK(c) ((unsigned char)((c) & 0xff)) - -/* Assert a build-time dependency, as an expression. - - Your compile will fail if the condition isn't true, or can't be evaluated - by the compiler. This can be used in an expression: its value is 0. - - Example: - - #define foo_to_char(foo) \ - ((char *)(foo) \ - + Py_BUILD_ASSERT_EXPR(offsetof(struct foo, string) == 0)) - - Written by Rusty Russell, public domain, http://ccodearchive.net/ */ -#define Py_BUILD_ASSERT_EXPR(cond) \ - (sizeof(char [1 - 2*!(cond)]) - 1) - -#define Py_BUILD_ASSERT(cond) do { \ - (void)Py_BUILD_ASSERT_EXPR(cond); \ - } while (0) - -/* Get the number of elements in a visible array - - This does not work on pointers, or arrays declared as [], or function - parameters. With correct compiler support, such usage will cause a build - error (see Py_BUILD_ASSERT_EXPR). - - Written by Rusty Russell, public domain, http://ccodearchive.net/ - - Requires at GCC 3.1+ */ -// Simplified by "0 &&" -#if 0 && (defined(__GNUC__) && !defined(__STRICT_ANSI__) && \ - (((__GNUC__ == 3) && (__GNU_MINOR__ >= 1)) || (__GNUC__ >= 4))) -/* Two gcc extensions. - &a[0] degrades to a pointer: a different type from an array */ -#define Py_ARRAY_LENGTH(array) \ - (sizeof(array) / sizeof((array)[0]) \ - + Py_BUILD_ASSERT_EXPR(!__builtin_types_compatible_p(typeof(array), \ - typeof(&(array)[0])))) -#else -#define Py_ARRAY_LENGTH(array) \ - (sizeof(array) / sizeof((array)[0])) -#endif - - -/* Define macros for inline documentation. */ -#define PyDoc_VAR(name) static char name[] -#define PyDoc_STRVAR(name,str) PyDoc_VAR(name) = PyDoc_STR(str) -#ifdef WITH_DOC_STRINGS -#define PyDoc_STR(str) str -#else -#define PyDoc_STR(str) "" -#endif - -/* Below "a" is a power of 2. */ -/* Round down size "n" to be a multiple of "a". */ -#define _Py_SIZE_ROUND_DOWN(n, a) ((size_t)(n) & ~(size_t)((a) - 1)) -/* Round up size "n" to be a multiple of "a". */ -#define _Py_SIZE_ROUND_UP(n, a) (((size_t)(n) + \ - (size_t)((a) - 1)) & ~(size_t)((a) - 1)) -/* Round pointer "p" down to the closest "a"-aligned address <= "p". */ -#define _Py_ALIGN_DOWN(p, a) ((void *)((uintptr_t)(p) & ~(uintptr_t)((a) - 1))) -/* Round pointer "p" up to the closest "a"-aligned address >= "p". */ -#define _Py_ALIGN_UP(p, a) ((void *)(((uintptr_t)(p) + \ - (uintptr_t)((a) - 1)) & ~(uintptr_t)((a) - 1))) -/* Check if pointer "p" is aligned to "a"-bytes boundary. */ -#define _Py_IS_ALIGNED(p, a) (!((uintptr_t)(p) & (uintptr_t)((a) - 1))) - -#ifdef __GNUC__ -#define Py_UNUSED(name) _unused_ ## name __attribute__((unused)) -#else -#define Py_UNUSED(name) _unused_ ## name -#endif - -#endif /* Py_PYMACRO_H */ - -// from typeobject.c -static int -extra_ivars(PyTypeObject *type, PyTypeObject *base) -{ - size_t t_size = type->tp_basicsize; - size_t b_size = base->tp_basicsize; - - assert(t_size >= b_size); /* Else type smaller than base! */ - if (type->tp_itemsize || base->tp_itemsize) { - /* If itemsize is involved, stricter rules */ - return t_size != b_size || - type->tp_itemsize != base->tp_itemsize; - } - if (type->tp_weaklistoffset && base->tp_weaklistoffset == 0 && - type->tp_weaklistoffset + sizeof(PyObject *) == t_size && - type->tp_flags & Py_TPFLAGS_HEAPTYPE) - t_size -= sizeof(PyObject *); - if (type->tp_dictoffset && base->tp_dictoffset == 0 && - type->tp_dictoffset + sizeof(PyObject *) == t_size && - type->tp_flags & Py_TPFLAGS_HEAPTYPE) - t_size -= sizeof(PyObject *); - - return t_size != b_size; -} - -static void -clear_slots(PyTypeObject *type, PyObject *self) -{ - Py_ssize_t i, n; - PyMemberDef *mp; - - n = Py_SIZE(type); - mp = PyHeapType_GET_MEMBERS((PyHeapTypeObject *)type); - for (i = 0; i < n; i++, mp++) { - if (mp->type == T_OBJECT_EX && !(mp->flags & READONLY)) { - char *addr = (char *)self + mp->offset; - PyObject *obj = *(PyObject **)addr; - if (obj != NULL) { - *(PyObject **)addr = NULL; - Py_DECREF(obj); - } - } - } -} - -static void -subtype_dealloc(PyObject *self) -{ - PyTypeObject *type, *base; - destructor basedealloc; - PyThreadState *tstate = PyThreadState_GET(); - - /* Extract the type; we expect it to be a heap type */ - type = Py_TYPE(self); - assert(type->tp_flags & Py_TPFLAGS_HEAPTYPE); - - /* Test whether the type has GC exactly once */ - - if (!PyType_IS_GC(type)) { - /* It's really rare to find a dynamic type that doesn't have - GC; it can only happen when deriving from 'object' and not - adding any slots or instance variables. This allows - certain simplifications: there's no need to call - clear_slots(), or DECREF the dict, or clear weakrefs. */ - - /* Maybe call finalizer; exit early if resurrected */ - if (type->tp_del) { - type->tp_del(self); - if (self->ob_refcnt > 0) - return; - } - - /* Find the nearest base with a different tp_dealloc */ - base = type; - while ((basedealloc = base->tp_dealloc) == subtype_dealloc) { - assert(Py_SIZE(base) == 0); - base = base->tp_base; - assert(base); - } - - /* Extract the type again; tp_del may have changed it */ - type = Py_TYPE(self); - - /* Call the base tp_dealloc() */ - assert(basedealloc); - basedealloc(self); - - /* Can't reference self beyond this point */ - Py_DECREF(type); - - /* Done */ - return; - } - - /* We get here only if the type has GC */ - - /* UnTrack and re-Track around the trashcan macro, alas */ - /* See explanation at end of function for full disclosure */ - PyObject_GC_UnTrack(self); - ++_PyTrash_delete_nesting; - ++ tstate->trash_delete_nesting; - Py_TRASHCAN_SAFE_BEGIN(self); - --_PyTrash_delete_nesting; - -- tstate->trash_delete_nesting; - /* DO NOT restore GC tracking at this point. weakref callbacks - * (if any, and whether directly here or indirectly in something we - * call) may trigger GC, and if self is tracked at that point, it - * will look like trash to GC and GC will try to delete self again. - */ - - /* Find the nearest base with a different tp_dealloc */ - base = type; - while ((basedealloc = base->tp_dealloc) == subtype_dealloc) { - base = base->tp_base; - assert(base); - } - - /* If we added a weaklist, we clear it. Do this *before* calling - the finalizer (__del__), clearing slots, or clearing the instance - dict. */ - - if (type->tp_weaklistoffset && !base->tp_weaklistoffset) - PyObject_ClearWeakRefs(self); - - /* Maybe call finalizer; exit early if resurrected */ - if (type->tp_del) { - _PyObject_GC_TRACK(self); - type->tp_del(self); - if (self->ob_refcnt > 0) - goto endlabel; /* resurrected */ - else - _PyObject_GC_UNTRACK(self); - /* New weakrefs could be created during the finalizer call. - If this occurs, clear them out without calling their - finalizers since they might rely on part of the object - being finalized that has already been destroyed. */ - if (type->tp_weaklistoffset && !base->tp_weaklistoffset) { - /* Modeled after GET_WEAKREFS_LISTPTR() */ - PyWeakReference **list = (PyWeakReference **) \ - PyObject_GET_WEAKREFS_LISTPTR(self); - while (*list) - _PyWeakref_ClearRef(*list); - } - } - - /* Clear slots up to the nearest base with a different tp_dealloc */ - base = type; - while (base->tp_dealloc == subtype_dealloc) { - if (Py_SIZE(base)) - clear_slots(base, self); - base = base->tp_base; - assert(base); - } - - /* If we added a dict, DECREF it */ - if (type->tp_dictoffset && !base->tp_dictoffset) { - PyObject **dictptr = _PyObject_GetDictPtr(self); - if (dictptr != NULL) { - PyObject *dict = *dictptr; - if (dict != NULL) { - Py_DECREF(dict); - *dictptr = NULL; - } - } - } - - /* Extract the type again; tp_del may have changed it */ - type = Py_TYPE(self); - - /* Call the base tp_dealloc(); first retrack self if - * basedealloc knows about gc. - */ - if (PyType_IS_GC(base)) - _PyObject_GC_TRACK(self); - assert(basedealloc); - basedealloc(self); - - /* Can't reference self beyond this point */ - Py_DECREF(type); - - endlabel: - ++_PyTrash_delete_nesting; - ++ tstate->trash_delete_nesting; - Py_TRASHCAN_SAFE_END(self); - --_PyTrash_delete_nesting; - -- tstate->trash_delete_nesting; - - /* Explanation of the weirdness around the trashcan macros: - - Q. What do the trashcan macros do? - - A. Read the comment titled "Trashcan mechanism" in object.h. - For one, this explains why there must be a call to GC-untrack - before the trashcan begin macro. Without understanding the - trashcan code, the answers to the following questions don't make - sense. - - Q. Why do we GC-untrack before the trashcan and then immediately - GC-track again afterward? - - A. In the case that the base class is GC-aware, the base class - probably GC-untracks the object. If it does that using the - UNTRACK macro, this will crash when the object is already - untracked. Because we don't know what the base class does, the - only safe thing is to make sure the object is tracked when we - call the base class dealloc. But... The trashcan begin macro - requires that the object is *untracked* before it is called. So - the dance becomes: - - GC untrack - trashcan begin - GC track - - Q. Why did the last question say "immediately GC-track again"? - It's nowhere near immediately. - - A. Because the code *used* to re-track immediately. Bad Idea. - self has a refcount of 0, and if gc ever gets its hands on it - (which can happen if any weakref callback gets invoked), it - looks like trash to gc too, and gc also tries to delete self - then. But we're already deleting self. Double deallocation is - a subtle disaster. - - Q. Why the bizarre (net-zero) manipulation of - _PyTrash_delete_nesting around the trashcan macros? - - A. Some base classes (e.g. list) also use the trashcan mechanism. - The following scenario used to be possible: - - - suppose the trashcan level is one below the trashcan limit - - - subtype_dealloc() is called - - - the trashcan limit is not yet reached, so the trashcan level - is incremented and the code between trashcan begin and end is - executed - - - this destroys much of the object's contents, including its - slots and __dict__ - - - basedealloc() is called; this is really list_dealloc(), or - some other type which also uses the trashcan macros - - - the trashcan limit is now reached, so the object is put on the - trashcan's to-be-deleted-later list - - - basedealloc() returns - - - subtype_dealloc() decrefs the object's type - - - subtype_dealloc() returns - - - later, the trashcan code starts deleting the objects from its - to-be-deleted-later list - - - subtype_dealloc() is called *AGAIN* for the same object - - - at the very least (if the destroyed slots and __dict__ don't - cause problems) the object's type gets decref'ed a second - time, which is *BAD*!!! - - The remedy is to make sure that if the code between trashcan - begin and end in subtype_dealloc() is called, the code between - trashcan begin and end in basedealloc() will also be called. - This is done by decrementing the level after passing into the - trashcan block, and incrementing it just before leaving the - block. - - But now it's possible that a chain of objects consisting solely - of objects whose deallocator is subtype_dealloc() will defeat - the trashcan mechanism completely: the decremented level means - that the effective level never reaches the limit. Therefore, we - *increment* the level *before* entering the trashcan block, and - matchingly decrement it after leaving. This means the trashcan - code will trigger a little early, but that's no big deal. - - Q. Are there any live examples of code in need of all this - complexity? - - A. Yes. See SF bug 668433 for code that crashed (when Python was - compiled in debug mode) before the trashcan level manipulations - were added. For more discussion, see SF patches 581742, 575073 - and bug 574207. - */ -} - -static PyTypeObject * -solid_base(PyTypeObject *type) -{ - PyTypeObject *base; - - if (type->tp_base) - base = solid_base(type->tp_base); - else - base = &PyBaseObject_Type; - if (extra_ivars(type, base)) - return type; - else - return base; -} - -/* Calculate the best base amongst multiple base classes. - This is the first one that's on the path to the "solid base". */ - -static PyTypeObject * -best_base(PyObject *bases) -{ - Py_ssize_t i, n; - PyTypeObject *base, *winner, *candidate, *base_i; - PyObject *base_proto; - - assert(PyTuple_Check(bases)); - n = PyTuple_GET_SIZE(bases); - assert(n > 0); - base = NULL; - winner = NULL; - for (i = 0; i < n; i++) { - base_proto = PyTuple_GET_ITEM(bases, i); - if (PyClass_Check(base_proto)) - continue; - if (!PyType_Check(base_proto)) { - PyErr_SetString( - PyExc_TypeError, - "bases must be types"); - return NULL; - } - base_i = (PyTypeObject *)base_proto; - if (base_i->tp_dict == NULL) { - if (PyType_Ready(base_i) < 0) - return NULL; - } - if (!PyType_HasFeature(base_i, Py_TPFLAGS_BASETYPE)) { - PyErr_Format(PyExc_TypeError, - "type '%.100s' is not an acceptable base type", - base_i->tp_name); - return NULL; - } - candidate = solid_base(base_i); - if (winner == NULL) { - winner = candidate; - base = base_i; - } - else if (PyType_IsSubtype(winner, candidate)) - ; - else if (PyType_IsSubtype(candidate, winner)) { - winner = candidate; - base = base_i; - } - else { - PyErr_SetString( - PyExc_TypeError, - "multiple bases have " - "instance lay-out conflict"); - return NULL; - } - } - if (base == NULL) - PyErr_SetString(PyExc_TypeError, - "a new-style class can't have only classic bases"); - return base; -} - -static const short slotoffsets[] = { - -1, /* invalid slot */ -/* Generated by typeslots.py */ -0, -0, -offsetof(PyHeapTypeObject, as_mapping.mp_ass_subscript), -offsetof(PyHeapTypeObject, as_mapping.mp_length), -offsetof(PyHeapTypeObject, as_mapping.mp_subscript), -offsetof(PyHeapTypeObject, as_number.nb_absolute), -offsetof(PyHeapTypeObject, as_number.nb_add), -offsetof(PyHeapTypeObject, as_number.nb_and), -offsetof(PyHeapTypeObject, as_number.nb_nonzero), -offsetof(PyHeapTypeObject, as_number.nb_divmod), -offsetof(PyHeapTypeObject, as_number.nb_float), -offsetof(PyHeapTypeObject, as_number.nb_floor_divide), -offsetof(PyHeapTypeObject, as_number.nb_index), -offsetof(PyHeapTypeObject, as_number.nb_inplace_add), -offsetof(PyHeapTypeObject, as_number.nb_inplace_and), -offsetof(PyHeapTypeObject, as_number.nb_inplace_floor_divide), -offsetof(PyHeapTypeObject, as_number.nb_inplace_lshift), -offsetof(PyHeapTypeObject, as_number.nb_inplace_multiply), -offsetof(PyHeapTypeObject, as_number.nb_inplace_or), -offsetof(PyHeapTypeObject, as_number.nb_inplace_power), -offsetof(PyHeapTypeObject, as_number.nb_inplace_remainder), -offsetof(PyHeapTypeObject, as_number.nb_inplace_rshift), -offsetof(PyHeapTypeObject, as_number.nb_inplace_subtract), -offsetof(PyHeapTypeObject, as_number.nb_inplace_true_divide), -offsetof(PyHeapTypeObject, as_number.nb_inplace_xor), -offsetof(PyHeapTypeObject, as_number.nb_int), -offsetof(PyHeapTypeObject, as_number.nb_invert), -offsetof(PyHeapTypeObject, as_number.nb_lshift), -offsetof(PyHeapTypeObject, as_number.nb_multiply), -offsetof(PyHeapTypeObject, as_number.nb_negative), -offsetof(PyHeapTypeObject, as_number.nb_or), -offsetof(PyHeapTypeObject, as_number.nb_positive), -offsetof(PyHeapTypeObject, as_number.nb_power), -offsetof(PyHeapTypeObject, as_number.nb_remainder), -offsetof(PyHeapTypeObject, as_number.nb_rshift), -offsetof(PyHeapTypeObject, as_number.nb_subtract), -offsetof(PyHeapTypeObject, as_number.nb_true_divide), -offsetof(PyHeapTypeObject, as_number.nb_xor), -offsetof(PyHeapTypeObject, as_sequence.sq_ass_item), -offsetof(PyHeapTypeObject, as_sequence.sq_concat), -offsetof(PyHeapTypeObject, as_sequence.sq_contains), -offsetof(PyHeapTypeObject, as_sequence.sq_inplace_concat), -offsetof(PyHeapTypeObject, as_sequence.sq_inplace_repeat), -offsetof(PyHeapTypeObject, as_sequence.sq_item), -offsetof(PyHeapTypeObject, as_sequence.sq_length), -offsetof(PyHeapTypeObject, as_sequence.sq_repeat), -offsetof(PyHeapTypeObject, ht_type.tp_alloc), -offsetof(PyHeapTypeObject, ht_type.tp_base), -offsetof(PyHeapTypeObject, ht_type.tp_bases), -offsetof(PyHeapTypeObject, ht_type.tp_call), -offsetof(PyHeapTypeObject, ht_type.tp_clear), -offsetof(PyHeapTypeObject, ht_type.tp_dealloc), -offsetof(PyHeapTypeObject, ht_type.tp_del), -offsetof(PyHeapTypeObject, ht_type.tp_descr_get), -offsetof(PyHeapTypeObject, ht_type.tp_descr_set), -offsetof(PyHeapTypeObject, ht_type.tp_doc), -offsetof(PyHeapTypeObject, ht_type.tp_getattr), -offsetof(PyHeapTypeObject, ht_type.tp_getattro), -offsetof(PyHeapTypeObject, ht_type.tp_hash), -offsetof(PyHeapTypeObject, ht_type.tp_init), -offsetof(PyHeapTypeObject, ht_type.tp_is_gc), -offsetof(PyHeapTypeObject, ht_type.tp_iter), -offsetof(PyHeapTypeObject, ht_type.tp_iternext), -offsetof(PyHeapTypeObject, ht_type.tp_methods), -offsetof(PyHeapTypeObject, ht_type.tp_new), -offsetof(PyHeapTypeObject, ht_type.tp_repr), -offsetof(PyHeapTypeObject, ht_type.tp_richcompare), -offsetof(PyHeapTypeObject, ht_type.tp_setattr), -offsetof(PyHeapTypeObject, ht_type.tp_setattro), -offsetof(PyHeapTypeObject, ht_type.tp_str), -offsetof(PyHeapTypeObject, ht_type.tp_traverse), -offsetof(PyHeapTypeObject, ht_type.tp_members), -offsetof(PyHeapTypeObject, ht_type.tp_getset), -offsetof(PyHeapTypeObject, ht_type.tp_free), -offsetof(PyHeapTypeObject, as_number.nb_long), -offsetof(PyHeapTypeObject, as_number.nb_divide), -offsetof(PyHeapTypeObject, as_sequence.sq_slice), -}; - -PyObject * -PyType_FromSpecWithBases(PyType_Spec *spec, PyObject *bases) -{ - auto res = reinterpret_cast<PyHeapTypeObject *>(PyType_GenericAlloc(&PyType_Type, 0)); - PyTypeObject *type, *base; - PyObject *modname; - auto res_start = reinterpret_cast<char *>(res); - PyType_Slot *slot; - - /* Set the type name and qualname */ - auto s = const_cast<char *>(strrchr(spec->name, '.')); // C++11 - if (s == NULL) - s = const_cast<char *>(spec->name); - else - s++; - - if (res == NULL) - return NULL; - type = &res->ht_type; - /* The flags must be initialized early, before the GC traverses us */ - type->tp_flags = spec->flags | Py_TPFLAGS_HEAPTYPE; - // was PyUnicode_FromString in Python 3 - res->ht_name = PyString_FromString(s); - if (!res->ht_name) - goto fail; - // no ht_qualname in Python 2 - // res->ht_qualname = res->ht_name; - // Py_INCREF(res->ht_qualname); - type->tp_name = spec->name; - if (!type->tp_name) - goto fail; - - /* Adjust for empty tuple bases */ - if (!bases) { - base = &PyBaseObject_Type; - /* See whether Py_tp_base(s) was specified */ - for (slot = spec->slots; slot->slot; slot++) { - if (slot->slot == Py_tp_base) - base = (PyTypeObject *)slot->pfunc; // C++11 - else if (slot->slot == Py_tp_bases) { - bases = (PyObject *)slot->pfunc; // C++11 - Py_INCREF(bases); - } - } - if (!bases) - bases = PyTuple_Pack(1, base); - if (!bases) - goto fail; - } - else - Py_INCREF(bases); - - /* Calculate best base, and check that all bases are type objects */ - base = best_base(bases); - if (base == NULL) { - goto fail; - } - if (!PyType_HasFeature(base, Py_TPFLAGS_BASETYPE)) { - PyErr_Format(PyExc_TypeError, - "type '%.100s' is not an acceptable base type", - base->tp_name); - goto fail; - } - - /* Initialize essential fields */ - // no async in Python 2 - // type->tp_as_async = &res->as_async; - type->tp_as_number = &res->as_number; - type->tp_as_sequence = &res->as_sequence; - type->tp_as_mapping = &res->as_mapping; - type->tp_as_buffer = &res->as_buffer; - /* Set tp_base and tp_bases */ - type->tp_bases = bases; - bases = NULL; - Py_INCREF(base); - type->tp_base = base; - - type->tp_basicsize = spec->basicsize; - type->tp_itemsize = spec->itemsize; - - for (slot = spec->slots; slot->slot; slot++) { - if (slot->slot < 0 - || (size_t)slot->slot >= Py_ARRAY_LENGTH(slotoffsets)) { - PyErr_SetString(PyExc_RuntimeError, "invalid slot offset"); - goto fail; - } - if (slot->slot == Py_tp_base || slot->slot == Py_tp_bases) - /* Processed above */ - continue; - *reinterpret_cast<void **>(res_start + slotoffsets[slot->slot]) = slot->pfunc; - - /* need to make a copy of the docstring slot, which usually - points to a static string literal */ - if (slot->slot == Py_tp_doc) { - // No signature in Python 2 - // const char *old_doc = _PyType_DocWithoutSignature(type->tp_name, slot->pfunc); - const char *old_doc = (const char *)slot->pfunc; - size_t len = strlen(old_doc)+1; - char *tp_doc = (char *)PyObject_MALLOC(len); // C++11 - if (tp_doc == NULL) { - PyErr_NoMemory(); - goto fail; - } - memcpy(tp_doc, old_doc, len); - type->tp_doc = tp_doc; - } - } - 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; - } - - if (PyType_Ready(type) < 0) - goto fail; - - // no ht_hached_keys in Python 2 - // if (type->tp_dictoffset) { - // res->ht_cached_keys = _PyDict_NewKeysForClass(); - // } - - /* Set type.__module__ */ - s = (char *)strrchr(spec->name, '.'); // c++11 - if (s != NULL) { - int err; - // was PyUnicode_FromStringAndSize in Python 3 - modname = PyString_FromStringAndSize( - spec->name, (Py_ssize_t)(s - spec->name)); - if (modname == NULL) { - goto fail; - } - // no PyId_ things in Python 2 - // err = _PyDict_SetItemId(type->tp_dict, &PyId___module__, modname); - err = PyDict_SetItemString(type->tp_dict, "__module__", modname); - Py_DECREF(modname); - if (err != 0) - goto fail; - } else { - // no PyErr_WarnFormat in Python 2 - // if (PyErr_WarnFormat(PyExc_DeprecationWarning, 1, - // "builtin type %.200s has no __module__ attribute", - // spec->name)) - char msg[250]; - sprintf(msg, "builtin type %.200s has no __module__ attribute", spec->name); - if (PyErr_WarnEx(PyExc_DeprecationWarning, msg, 1)) - goto fail; - } - - return reinterpret_cast<PyObject *>(res); - - fail: - Py_DECREF(res); - return NULL; -} - -PyObject * -PyType_FromSpec(PyType_Spec *spec) -{ - return PyType_FromSpecWithBases(spec, NULL); -} - -void * -PyType_GetSlot(PyTypeObject *type, int slot) -{ - if (!PyType_HasFeature(type, Py_TPFLAGS_HEAPTYPE) || slot < 0) { - PyErr_BadInternalCall(); - return NULL; - } - if ((size_t)slot >= Py_ARRAY_LENGTH(slotoffsets)) { - /* Extension module requesting slot from a future version */ - return NULL; - } - return *reinterpret_cast<void **>(reinterpret_cast<char *>(type) + slotoffsets[slot]); -} - -} // extern "C" -#endif // PY_MAJOR_VERSION < 3 diff --git a/sources/shiboken2/libshiboken/typespec.h b/sources/shiboken2/libshiboken/typespec.h deleted file mode 100644 index 193b654c2..000000000 --- a/sources/shiboken2/libshiboken/typespec.h +++ /dev/null @@ -1,153 +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 TYPESPEC_H -#define TYPESPEC_H - -#include "sbkpython.h" -#include "shibokenmacros.h" - -#if PY_MAJOR_VERSION < 3 -extern "C" -{ - -typedef struct{ - int slot; // slot is somehow reserved in Qt /* slot id, see below */ - void *pfunc; /* function pointer */ -} PyType_Slot; - -typedef struct{ - const char *name; - int basicsize; - int itemsize; - unsigned int flags; - PyType_Slot *slots; /* terminated by slot==0. */ -} PyType_Spec; - -LIBSHIBOKEN_API PyObject *PyType_FromSpec(PyType_Spec *); -#if !defined(Py_LIMITED_API) || Py_LIMITED_API+0 >= 0x03030000 -LIBSHIBOKEN_API PyObject *PyType_FromSpecWithBases(PyType_Spec *, PyObject *); -#endif -#if !defined(Py_LIMITED_API) || Py_LIMITED_API+0 >= 0x03040000 -LIBSHIBOKEN_API void *PyType_GetSlot(PyTypeObject *, int); -#endif - -// from typeslots.h -/* Do not renumber the file; these numbers are part of the stable ABI. */ -/* Disabled, see #10181 */ -#undef Py_bf_getbuffer -#undef Py_bf_releasebuffer -#define Py_mp_ass_subscript 3 -#define Py_mp_length 4 -#define Py_mp_subscript 5 -#define Py_nb_absolute 6 -#define Py_nb_add 7 -#define Py_nb_and 8 -#define Py_nb_nonzero 9 -#define Py_nb_divmod 10 -#define Py_nb_float 11 -#define Py_nb_floor_divide 12 -#define Py_nb_index 13 -#define Py_nb_inplace_add 14 -#define Py_nb_inplace_and 15 -#define Py_nb_inplace_floor_divide 16 -#define Py_nb_inplace_lshift 17 -#define Py_nb_inplace_multiply 18 -#define Py_nb_inplace_or 19 -#define Py_nb_inplace_power 20 -#define Py_nb_inplace_remainder 21 -#define Py_nb_inplace_rshift 22 -#define Py_nb_inplace_subtract 23 -#define Py_nb_inplace_true_divide 24 -#define Py_nb_inplace_xor 25 -#define Py_nb_int 26 -#define Py_nb_invert 27 -#define Py_nb_lshift 28 -#define Py_nb_multiply 29 -#define Py_nb_negative 30 -#define Py_nb_or 31 -#define Py_nb_positive 32 -#define Py_nb_power 33 -#define Py_nb_remainder 34 -#define Py_nb_rshift 35 -#define Py_nb_subtract 36 -#define Py_nb_true_divide 37 -#define Py_nb_xor 38 -#define Py_sq_ass_item 39 -#define Py_sq_concat 40 -#define Py_sq_contains 41 -#define Py_sq_inplace_concat 42 -#define Py_sq_inplace_repeat 43 -#define Py_sq_item 44 -#define Py_sq_length 45 -#define Py_sq_repeat 46 -#define Py_tp_alloc 47 -#define Py_tp_base 48 -#define Py_tp_bases 49 -#define Py_tp_call 50 -#define Py_tp_clear 51 -#define Py_tp_dealloc 52 -#define Py_tp_del 53 -#define Py_tp_descr_get 54 -#define Py_tp_descr_set 55 -#define Py_tp_doc 56 -#define Py_tp_getattr 57 -#define Py_tp_getattro 58 -#define Py_tp_hash 59 -#define Py_tp_init 60 -#define Py_tp_is_gc 61 -#define Py_tp_iter 62 -#define Py_tp_iternext 63 -#define Py_tp_methods 64 -#define Py_tp_new 65 -#define Py_tp_repr 66 -#define Py_tp_richcompare 67 -#define Py_tp_setattr 68 -#define Py_tp_setattro 69 -#define Py_tp_str 70 -#define Py_tp_traverse 71 -#define Py_tp_members 72 -#define Py_tp_getset 73 -#define Py_tp_free 74 -#define Py_nb_long 75 -#define Py_nb_divide 76 -#define Py_sq_slice 77 -} // extern "C" -#endif // PY_MAJOR_VERSION < 3 -#endif // TYPESPEC_H diff --git a/sources/shiboken2/libshiboken/voidptr.cpp b/sources/shiboken2/libshiboken/voidptr.cpp deleted file mode 100644 index d4ce58c87..000000000 --- a/sources/shiboken2/libshiboken/voidptr.cpp +++ /dev/null @@ -1,481 +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); - #ifdef IS_PY3K - PyObject *s = PyUnicode_FromFormat("%s(%p, %zd, %s)", - #else - PyObject *s = PyBytes_FromFormat("%s(%p, %zd, %s)", - #endif - 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); - #ifdef IS_PY3K - PyObject *s = PyUnicode_FromFormat("%s(Address %p, Size %zd, isWritable %s)", - #else - PyObject *s = PyBytes_FromFormat("%s(Address %p, Size %zd, isWritable %s)", - #endif - 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 *)object_dealloc}, - {Py_tp_methods, (void *)SbkVoidPtrObject_methods}, - {0, nullptr} -}; -static PyType_Spec SbkVoidPtrType_spec = { - "shiboken2.libshiboken.VoidPtr", - sizeof(SbkVoidPtrObject), - 0, - Py_TPFLAGS_DEFAULT, - SbkVoidPtrType_slots, -}; - - -} - -PyTypeObject *SbkVoidPtrTypeF(void) -{ - static PyTypeObject *type = nullptr; - if (!type) - type = reinterpret_cast<PyTypeObject *>(PyType_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 |