aboutsummaryrefslogtreecommitdiffstats
path: root/sources/shiboken2/libshiboken
diff options
context:
space:
mode:
Diffstat (limited to 'sources/shiboken2/libshiboken')
-rw-r--r--sources/shiboken2/libshiboken/CMakeLists.txt77
-rw-r--r--sources/shiboken2/libshiboken/autodecref.h115
-rw-r--r--sources/shiboken2/libshiboken/basewrapper.cpp1518
-rw-r--r--sources/shiboken2/libshiboken/basewrapper.h451
-rw-r--r--sources/shiboken2/libshiboken/basewrapper_p.h287
-rw-r--r--sources/shiboken2/libshiboken/bindingmanager.cpp344
-rw-r--r--sources/shiboken2/libshiboken/bindingmanager.h109
-rw-r--r--sources/shiboken2/libshiboken/conversions.h731
-rw-r--r--sources/shiboken2/libshiboken/debugfreehook.cpp194
-rw-r--r--sources/shiboken2/libshiboken/debugfreehook.h61
-rw-r--r--sources/shiboken2/libshiboken/gilstate.cpp68
-rw-r--r--sources/shiboken2/libshiboken/gilstate.h63
-rw-r--r--sources/shiboken2/libshiboken/helper.cpp142
-rw-r--r--sources/shiboken2/libshiboken/helper.h136
-rw-r--r--sources/shiboken2/libshiboken/python25compat.h104
-rw-r--r--sources/shiboken2/libshiboken/sbkconverter.cpp572
-rw-r--r--sources/shiboken2/libshiboken/sbkconverter.h367
-rw-r--r--sources/shiboken2/libshiboken/sbkconverter_p.h574
-rw-r--r--sources/shiboken2/libshiboken/sbkdbg.h124
-rw-r--r--sources/shiboken2/libshiboken/sbkenum.cpp623
-rw-r--r--sources/shiboken2/libshiboken/sbkenum.h118
-rw-r--r--sources/shiboken2/libshiboken/sbkmodule.cpp124
-rw-r--r--sources/shiboken2/libshiboken/sbkmodule.h115
-rw-r--r--sources/shiboken2/libshiboken/sbkpython.h74
-rw-r--r--sources/shiboken2/libshiboken/sbkstring.cpp202
-rw-r--r--sources/shiboken2/libshiboken/sbkstring.h75
-rw-r--r--sources/shiboken2/libshiboken/sbkversion.h.in50
-rw-r--r--sources/shiboken2/libshiboken/shiboken.h60
-rw-r--r--sources/shiboken2/libshiboken/shibokenbuffer.cpp96
-rw-r--r--sources/shiboken2/libshiboken/shibokenbuffer.h85
-rw-r--r--sources/shiboken2/libshiboken/shibokenmacros.h63
-rw-r--r--sources/shiboken2/libshiboken/threadstatesaver.cpp69
-rw-r--r--sources/shiboken2/libshiboken/threadstatesaver.h66
-rw-r--r--sources/shiboken2/libshiboken/tmp-referencetopython/sbkconverter.cpp213
-rw-r--r--sources/shiboken2/libshiboken/tmp-referencetopython/sbkconverter.h191
-rw-r--r--sources/shiboken2/libshiboken/typeresolver.cpp162
-rw-r--r--sources/shiboken2/libshiboken/typeresolver.h139
37 files changed, 8562 insertions, 0 deletions
diff --git a/sources/shiboken2/libshiboken/CMakeLists.txt b/sources/shiboken2/libshiboken/CMakeLists.txt
new file mode 100644
index 000000000..9ec49d5bd
--- /dev/null
+++ b/sources/shiboken2/libshiboken/CMakeLists.txt
@@ -0,0 +1,77 @@
+project(libshiboken)
+
+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)
+
+#Find installed sparsehash
+find_path(SPARSEHASH_INCLUDE_PATH sparseconfig.h PATH_SUFFIXES "/google/sparsehash")
+if(SPARSEHASH_INCLUDE_PATH)
+ message(STATUS "Using system hash found in: ${SPARSEHASH_INCLUDE_PATH}")
+else()
+ set(SPARSEHASH_INCLUDE_PATH ${CMAKE_SOURCE_DIR}/ext/sparsehash)
+endif()
+
+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 "${libshiboken_MAJOR_VERSION}.${libshiboken_MINOR_VERSION}")
+
+set(libshiboken_SRC
+basewrapper.cpp
+debugfreehook.cpp
+gilstate.cpp
+helper.cpp
+sbkconverter.cpp
+sbkenum.cpp
+sbkmodule.cpp
+sbkstring.cpp
+bindingmanager.cpp
+threadstatesaver.cpp
+typeresolver.cpp
+shibokenbuffer.cpp
+)
+
+include_directories(${CMAKE_CURRENT_SOURCE_DIR}
+ ${CMAKE_CURRENT_BINARY_DIR}
+ ${SBK_PYTHON_INCLUDE_DIR}
+ ${SPARSEHASH_INCLUDE_PATH})
+add_library(libshiboken SHARED ${libshiboken_SRC})
+target_link_libraries(libshiboken ${SBK_PYTHON_LIBRARIES})
+set_target_properties(libshiboken PROPERTIES OUTPUT_NAME "shiboken2${shiboken2_SUFFIX}${PYTHON_EXTENSION_SUFFIX}"
+ VERSION ${libshiboken_VERSION}
+ SOVERSION ${libshiboken_SOVERSION}
+ DEFINE_SYMBOL LIBSHIBOKEN_EXPORTS)
+
+install(FILES
+ autodecref.h
+ basewrapper.h
+ bindingmanager.h
+ conversions.h
+ gilstate.h
+ helper.h
+ sbkconverter.h
+ sbkenum.h
+ sbkmodule.h
+ python25compat.h
+ sbkdbg.h
+ sbkstring.h
+ shiboken.h
+ shibokenmacros.h
+ threadstatesaver.h
+ typeresolver.h
+ shibokenbuffer.h
+ sbkpython.h
+ "${CMAKE_CURRENT_BINARY_DIR}/sbkversion.h"
+ DESTINATION include/shiboken2${shiboken2_SUFFIX})
+install(TARGETS libshiboken EXPORT shiboken2
+ LIBRARY DESTINATION "${LIB_INSTALL_DIR}"
+ ARCHIVE DESTINATION "${LIB_INSTALL_DIR}"
+ RUNTIME DESTINATION bin)
diff --git a/sources/shiboken2/libshiboken/autodecref.h b/sources/shiboken2/libshiboken/autodecref.h
new file mode 100644
index 000000000..1fefcc259
--- /dev/null
+++ b/sources/shiboken2/libshiboken/autodecref.h
@@ -0,0 +1,115 @@
+/****************************************************************************
+**
+** Copyright (C) 2016 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$
+**
+****************************************************************************/
+
+#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 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 == 0; }
+ /// Returns the pointer of the Python object being held.
+ inline PyObject* object() { return m_pyObj; }
+ inline operator PyObject*() { return m_pyObj; }
+ inline operator PyTupleObject*() { return reinterpret_cast<PyTupleObject*>(m_pyObj); }
+ inline operator bool() const { return m_pyObj; }
+ inline PyObject* operator->() { return m_pyObj; }
+
+ template<typename T>
+ T cast()
+ {
+ return reinterpret_cast<T>(m_pyObj);
+ }
+
+ /**
+ * Decref the current borrowed python reference and take the reference
+ * borrowed by \p other, so other.isNull() will return true.
+ */
+ void operator=(AutoDecRef& other)
+ {
+ Py_XDECREF(m_pyObj);
+ m_pyObj = other.m_pyObj;
+ other.m_pyObj = 0;
+ }
+
+ /**
+ * Decref the current borrowed python reference and borrow \p other.
+ */
+ void operator=(PyObject* other)
+ {
+ Py_XDECREF(m_pyObj);
+ m_pyObj = other;
+ }
+private:
+ PyObject* m_pyObj;
+ AutoDecRef(const AutoDecRef&);
+ AutoDecRef& operator=(const AutoDecRef&);
+};
+
+} // namespace Shiboken
+
+#endif // AUTODECREF_H
+
diff --git a/sources/shiboken2/libshiboken/basewrapper.cpp b/sources/shiboken2/libshiboken/basewrapper.cpp
new file mode 100644
index 000000000..b3f99a8a5
--- /dev/null
+++ b/sources/shiboken2/libshiboken/basewrapper.cpp
@@ -0,0 +1,1518 @@
+/****************************************************************************
+**
+** Copyright (C) 2016 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$
+**
+****************************************************************************/
+
+#include "basewrapper.h"
+#include "basewrapper_p.h"
+#include "sbkconverter.h"
+#include "sbkenum.h"
+#include "autodecref.h"
+#include "typeresolver.h"
+#include "gilstate.h"
+#include <string>
+#include <cstring>
+#include <cstddef>
+#include <set>
+#include <sstream>
+#include <algorithm>
+#include "threadstatesaver.h"
+
+namespace {
+ void _destroyParentInfo(SbkObject* obj, bool keepReference);
+}
+
+extern "C"
+{
+
+static void SbkObjectTypeDealloc(PyObject* pyObj);
+static PyObject* SbkObjectTypeTpNew(PyTypeObject* metatype, PyObject* args, PyObject* kwds);
+
+PyTypeObject SbkObjectType_Type = {
+ PyVarObject_HEAD_INIT(0, 0)
+ /*tp_name*/ "Shiboken.ObjectType",
+ /*tp_basicsize*/ sizeof(SbkObjectType),
+ /*tp_itemsize*/ 0,
+ /*tp_dealloc*/ SbkObjectTypeDealloc,
+ /*tp_print*/ 0,
+ /*tp_getattr*/ 0,
+ /*tp_setattr*/ 0,
+ /*tp_compare*/ 0,
+ /*tp_repr*/ 0,
+ /*tp_as_number*/ 0,
+ /*tp_as_sequence*/ 0,
+ /*tp_as_mapping*/ 0,
+ /*tp_hash*/ 0,
+ /*tp_call*/ 0,
+ /*tp_str*/ 0,
+ /*tp_getattro*/ 0,
+ /*tp_setattro*/ PyObject_GenericSetAttr,
+ /*tp_as_buffer*/ 0,
+ /*tp_flags*/ Py_TPFLAGS_DEFAULT|Py_TPFLAGS_BASETYPE,
+ /*tp_doc*/ 0,
+ /*tp_traverse*/ 0,
+ /*tp_clear*/ 0,
+ /*tp_richcompare*/ 0,
+ /*tp_weaklistoffset*/ 0,
+ /*tp_iter*/ 0,
+ /*tp_iternext*/ 0,
+ /*tp_methods*/ 0,
+ /*tp_members*/ 0,
+ /*tp_getset*/ 0,
+ /*tp_base*/ &PyType_Type,
+ /*tp_dict*/ 0,
+ /*tp_descr_get*/ 0,
+ /*tp_descr_set*/ 0,
+ /*tp_dictoffset*/ 0,
+ /*tp_init*/ 0,
+ /*tp_alloc*/ PyType_GenericAlloc,
+ /*tp_new*/ SbkObjectTypeTpNew,
+ /*tp_free*/ PyObject_GC_Del,
+ /*tp_is_gc*/ 0,
+ /*tp_bases*/ 0,
+ /*tp_mro*/ 0,
+ /*tp_cache*/ 0,
+ /*tp_subclasses*/ 0,
+ /*tp_weaklist*/ 0,
+ /*tp_del*/ 0,
+ /*tp_version_tag*/ 0
+};
+
+static PyObject *SbkObjectGetDict(PyObject* pObj, void *)
+{
+ SbkObject *obj = reinterpret_cast<SbkObject *>(pObj);
+ if (!obj->ob_dict)
+ obj->ob_dict = PyDict_New();
+ if (!obj->ob_dict)
+ return 0;
+ Py_INCREF(obj->ob_dict);
+ return obj->ob_dict;
+}
+
+static PyGetSetDef SbkObjectGetSetList[] = {
+ {const_cast<char*>("__dict__"), SbkObjectGetDict, 0, 0, 0},
+ {0, 0, 0, 0, 0} // Sentinel
+};
+
+static int SbkObject_traverse(PyObject* self, visitproc visit, void* arg)
+{
+ SbkObject* sbkSelf = reinterpret_cast<SbkObject*>(self);
+
+ //Visit children
+ Shiboken::ParentInfo* pInfo = sbkSelf->d->parentInfo;
+ if (pInfo) {
+ std::set<SbkObject*>::const_iterator it = pInfo->children.begin();
+ for(; it != pInfo->children.end(); ++it)
+ Py_VISIT(*it);
+ }
+
+ //Visit refs
+ Shiboken::RefCountMap* rInfo = sbkSelf->d->referredObjects;
+ if (rInfo) {
+ Shiboken::RefCountMap::const_iterator it = rInfo->begin();
+ for (; it != rInfo->end(); ++it) {
+ std::list<PyObject*>::const_iterator ref = it->second.begin();
+ for(; ref != it->second.end(); ++ref)
+ Py_VISIT(*ref);
+ }
+ }
+
+ if (sbkSelf->ob_dict)
+ Py_VISIT(sbkSelf->ob_dict);
+ return 0;
+}
+
+static int SbkObject_clear(PyObject* self)
+{
+ SbkObject* 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;
+}
+
+SbkObjectType SbkObject_Type = { { {
+ PyVarObject_HEAD_INIT(&SbkObjectType_Type, 0)
+ /*tp_name*/ "Shiboken.Object",
+ /*tp_basicsize*/ sizeof(SbkObject),
+ /*tp_itemsize*/ 0,
+ /*tp_dealloc*/ SbkDeallocWrapperWithPrivateDtor,
+ /*tp_print*/ 0,
+ /*tp_getattr*/ 0,
+ /*tp_setattr*/ 0,
+ /*tp_compare*/ 0,
+ /*tp_repr*/ 0,
+ /*tp_as_number*/ 0,
+ /*tp_as_sequence*/ 0,
+ /*tp_as_mapping*/ 0,
+ /*tp_hash*/ 0,
+ /*tp_call*/ 0,
+ /*tp_str*/ 0,
+ /*tp_getattro*/ 0,
+ /*tp_setattro*/ 0,
+ /*tp_as_buffer*/ 0,
+ /*tp_flags*/ Py_TPFLAGS_DEFAULT|Py_TPFLAGS_BASETYPE|Py_TPFLAGS_HAVE_GC,
+ /*tp_doc*/ 0,
+ /*tp_traverse*/ SbkObject_traverse,
+ /*tp_clear*/ SbkObject_clear,
+ /*tp_richcompare*/ 0,
+ /*tp_weaklistoffset*/ offsetof(SbkObject, weakreflist),
+ /*tp_iter*/ 0,
+ /*tp_iternext*/ 0,
+ /*tp_methods*/ 0,
+ /*tp_members*/ 0,
+ /*tp_getset*/ SbkObjectGetSetList,
+ /*tp_base*/ 0,
+ /*tp_dict*/ 0,
+ /*tp_descr_get*/ 0,
+ /*tp_descr_set*/ 0,
+ /*tp_dictoffset*/ offsetof(SbkObject, ob_dict),
+ /*tp_init*/ 0,
+ /*tp_alloc*/ 0,
+ /*tp_new*/ 0,
+ /*tp_free*/ 0,
+ /*tp_is_gc*/ 0,
+ /*tp_bases*/ 0,
+ /*tp_mro*/ 0,
+ /*tp_cache*/ 0,
+ /*tp_subclasses*/ 0,
+ /*tp_weaklist*/ 0,
+ /*tp_del*/ 0,
+ /*tp_version_tag*/ 0
+}, },
+ /*priv_data*/ 0
+};
+
+
+static void SbkDeallocWrapperCommon(PyObject* pyObj, bool canDelete)
+{
+ SbkObject* 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->tp_dealloc == SbkDeallocWrapper
+ || pyType->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.
+ 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
+ if (canDelete && sbkObj->d->hasOwnership && sbkObj->d->validCppObject) {
+ SbkObjectType* sbkType = reinterpret_cast<SbkObjectType*>(pyType);
+ if (sbkType->d->is_multicpp) {
+ Shiboken::DeallocVisitor visitor(sbkObj);
+ Shiboken::walkThroughClassHierarchy(pyObj->ob_type, &visitor);
+ } else {
+ void* cptr = sbkObj->d->cptr[0];
+ Shiboken::Object::deallocData(sbkObj, true);
+
+ Shiboken::ThreadStateSaver threadSaver;
+ if (Py_IsInitialized())
+ threadSaver.save();
+ sbkType->d->cpp_dtor(cptr);
+ }
+ } else {
+ Shiboken::Object::deallocData(sbkObj, true);
+ }
+
+ if (needTypeDecref)
+ Py_DECREF(pyType);
+}
+
+void SbkDeallocWrapper(PyObject* pyObj)
+{
+ SbkDeallocWrapperCommon(pyObj, true);
+}
+
+void SbkDeallocWrapperWithPrivateDtor(PyObject* self)
+{
+ SbkDeallocWrapperCommon(self, false);
+}
+
+void SbkObjectTypeDealloc(PyObject* pyObj)
+{
+ SbkObjectType* sbkType = reinterpret_cast<SbkObjectType*>(pyObj);
+
+ PyObject_GC_UnTrack(pyObj);
+ Py_TRASHCAN_SAFE_BEGIN(pyObj);
+ if (sbkType->d) {
+ if(sbkType->d->user_data && sbkType->d->d_func) {
+ sbkType->d->d_func(sbkType->d->user_data);
+ sbkType->d->user_data = 0;
+ }
+ free(sbkType->d->original_name);
+ sbkType->d->original_name = 0;
+ if (!Shiboken::ObjectType::isUserType(reinterpret_cast<PyTypeObject*>(sbkType)))
+ Shiboken::Conversions::deleteConverter(sbkType->d->converter);
+ delete sbkType->d;
+ sbkType->d = 0;
+ }
+ Py_TRASHCAN_SAFE_END(pyObj);
+}
+
+PyObject* SbkObjectTypeTpNew(PyTypeObject* metatype, PyObject* args, PyObject* kwds)
+{
+#ifndef IS_PY3K
+ // 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.
+ PyObject* name;
+ PyObject* pyBases;
+ PyObject* dict;
+ static const char* kwlist[] = { "name", "bases", "dict", 0};
+
+ if (!PyArg_ParseTupleAndKeywords(args, kwds, "SO!O!:sbktype", (char**)kwlist,
+ &name,
+ &PyTuple_Type, &pyBases,
+ &PyDict_Type, &dict))
+ return NULL;
+
+ for(int i=0, i_max=PyTuple_GET_SIZE(pyBases); i < i_max; i++) {
+ PyObject* baseType = PyTuple_GET_ITEM(pyBases, i);
+ 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
+
+ // The meta type creates a new type when the Python programmer extends a wrapped C++ class.
+ SbkObjectType* newType = reinterpret_cast<SbkObjectType*>(PyType_Type.tp_new(metatype, args, kwds));
+ if (!newType)
+ return 0;
+
+ Shiboken::ObjectType::initPrivateData(newType);
+ SbkObjectTypePrivate* d = newType->d;
+
+ std::list<SbkObjectType*> bases = Shiboken::getCppBaseClasses(reinterpret_cast<PyTypeObject*>(newType));
+ if (bases.size() == 1) {
+ SbkObjectTypePrivate* parentType = bases.front()->d;
+ d->mi_offsets = parentType->mi_offsets;
+ d->mi_init = parentType->mi_init;
+ d->mi_specialcast = parentType->mi_specialcast;
+ d->type_discovery = parentType->type_discovery;
+ d->cpp_dtor = parentType->cpp_dtor;
+ d->is_multicpp = 0;
+ d->converter = parentType->converter;
+ } else {
+ d->mi_offsets = 0;
+ d->mi_init = 0;
+ d->mi_specialcast = 0;
+ d->type_discovery = 0;
+ d->cpp_dtor = 0;
+ d->is_multicpp = 1;
+ d->converter = 0;
+ }
+ if (bases.size() == 1)
+ d->original_name = strdup(bases.front()->d->original_name);
+ else
+ d->original_name = strdup("object");
+ d->user_data = 0;
+ d->d_func = 0;
+ d->is_user_type = 1;
+
+ std::list<SbkObjectType*>::const_iterator it = bases.begin();
+ for (; it != bases.end(); ++it) {
+ if ((*it)->d->subtype_init)
+ (*it)->d->subtype_init(newType, args, kwds);
+ }
+
+ return reinterpret_cast<PyObject*>(newType);
+}
+
+PyObject* SbkObjectTpNew(PyTypeObject* subtype, PyObject*, PyObject*)
+{
+ SbkObject* self = PyObject_GC_New(SbkObject, subtype);
+ Py_INCREF(reinterpret_cast<PyObject*>(subtype));
+ SbkObjectPrivate* d = new SbkObjectPrivate;
+
+ SbkObjectType* sbkType = reinterpret_cast<SbkObjectType*>(subtype);
+ int numBases = ((sbkType->d && sbkType->d->is_multicpp) ? Shiboken::getNumberOfCppBaseClasses(subtype) : 1);
+ d->cptr = new void*[numBases];
+ std::memset(d->cptr, 0, sizeof(void*)*numBases);
+ d->hasOwnership = 1;
+ d->containsCppWrapper = 0;
+ d->validCppObject = 0;
+ d->parentInfo = 0;
+ d->referredObjects = 0;
+ d->cppObjectCreated = 0;
+ self->ob_dict = 0;
+ self->weakreflist = 0;
+ self->d = d;
+ PyObject_GC_Track(reinterpret_cast<PyObject*>(self));
+ return reinterpret_cast<PyObject*>(self);
+}
+
+
+} //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
+{
+
+static void decRefPyObjectList(const std::list<PyObject*> &pyObj, PyObject* skip = 0);
+
+static void _walkThroughClassHierarchy(PyTypeObject* currentType, HierarchyVisitor* visitor)
+{
+ PyObject* bases = currentType->tp_bases;
+ Py_ssize_t numBases = PyTuple_GET_SIZE(bases);
+ for (int i = 0; i < numBases; ++i) {
+ PyTypeObject* type = reinterpret_cast<PyTypeObject*>(PyTuple_GET_ITEM(bases, i));
+
+ if (!PyType_IsSubtype(type, reinterpret_cast<PyTypeObject*>(&SbkObject_Type))) {
+ continue;
+ } else {
+ SbkObjectType* sbkType = reinterpret_cast<SbkObjectType*>(type);
+ if (sbkType->d->is_user_type)
+ _walkThroughClassHierarchy(type, visitor);
+ else
+ visitor->visit(sbkType);
+ }
+ if (visitor->wasFinished())
+ break;
+ }
+}
+
+void walkThroughClassHierarchy(PyTypeObject* currentType, HierarchyVisitor* visitor)
+{
+ _walkThroughClassHierarchy(currentType, visitor);
+ visitor->done();
+}
+
+
+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, 0));
+#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 ----------------------------------------------------------
+
+void DtorCallerVisitor::visit(SbkObjectType* node)
+{
+ m_ptrs.push_back(std::make_pair(m_pyObj->d->cptr[m_ptrs.size()], node));
+}
+
+void DtorCallerVisitor::done()
+{
+ std::list<std::pair<void*, SbkObjectType*> >::const_iterator it = m_ptrs.begin();
+ for (; it != m_ptrs.end(); ++it) {
+ Shiboken::ThreadStateSaver threadSaver;
+ threadSaver.save();
+ it->second->d->cpp_dtor(it->first);
+ }
+}
+
+void DeallocVisitor::done()
+{
+ Shiboken::Object::deallocData(m_pyObj, true);
+ DtorCallerVisitor::done();
+}
+
+namespace Module { void init(); }
+namespace Conversions { void init(); }
+
+void init()
+{
+ static bool shibokenAlreadInitialised = false;
+ if (shibokenAlreadInitialised)
+ return;
+
+ Module::init();
+ Conversions::init();
+
+ initTypeResolver();
+ PyEval_InitThreads();
+
+ //Init private data
+ Shiboken::ObjectType::initPrivateData(&SbkObject_Type);
+
+ if (PyType_Ready(&SbkEnumType_Type) < 0)
+ Py_FatalError("[libshiboken] Failed to initialise Shiboken.SbkEnumType metatype.");
+
+ if (PyType_Ready(&SbkObjectType_Type) < 0)
+ Py_FatalError("[libshiboken] Failed to initialise Shiboken.BaseWrapperType metatype.");
+
+ if (PyType_Ready(reinterpret_cast<PyTypeObject *>(&SbkObject_Type)) < 0)
+ Py_FatalError("[libshiboken] Failed to initialise Shiboken.BaseWrapper type.");
+
+ shibokenAlreadInitialised = true;
+}
+
+void setErrorAboutWrongArguments(PyObject* args, const char* funcName, const char** cppOverloads)
+{
+ std::string msg;
+ std::string params;
+ if (args) {
+ if (PyTuple_Check(args)) {
+ for (Py_ssize_t i = 0, max = PyTuple_GET_SIZE(args); i < max; ++i) {
+ if (i)
+ params += ", ";
+ PyObject* arg = PyTuple_GET_ITEM(args, i);
+ params += arg->ob_type->tp_name;
+ }
+ } else {
+ params = args->ob_type->tp_name;
+ }
+ }
+
+ if (!cppOverloads) {
+ msg = "'" + std::string(funcName) + "' called with wrong argument types: " + params;
+ } else {
+ msg = "'" + std::string(funcName) + "' called with wrong argument types:\n ";
+ msg += funcName;
+ msg += '(';
+ msg += params;
+ msg += ")\n";
+ msg += "Supported signatures:";
+ for (int i = 0; cppOverloads[i]; ++i) {
+ msg += "\n ";
+ msg += funcName;
+ msg += '(';
+ msg += cppOverloads[i];
+ msg += ')';
+ }
+ }
+ PyErr_SetString(PyExc_TypeError, msg.c_str());
+
+}
+
+class FindBaseTypeVisitor : public HierarchyVisitor
+{
+ public:
+ FindBaseTypeVisitor(PyTypeObject* typeToFind) : m_found(false), m_typeToFind(typeToFind) {}
+ virtual void visit(SbkObjectType* node)
+ {
+ if (reinterpret_cast<PyTypeObject*>(node) == m_typeToFind) {
+ m_found = true;
+ finish();
+ }
+ }
+ bool found() const { return m_found; }
+
+ private:
+ bool m_found;
+ PyTypeObject* m_typeToFind;
+};
+
+std::list<SbkObject*> splitPyObject(PyObject* pyObj)
+{
+ std::list<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;
+}
+
+static void decRefPyObjectList(const std::list<PyObject*>& lst, PyObject *skip)
+{
+ std::list<PyObject*>::const_iterator iter = lst.begin();
+ while(iter != lst.end()) {
+ if (*iter != skip)
+ Py_DECREF(*iter);
+ ++iter;
+ }
+}
+
+namespace ObjectType
+{
+
+bool checkType(PyTypeObject* type)
+{
+ return PyType_IsSubtype(type, reinterpret_cast<PyTypeObject*>(&SbkObject_Type));
+}
+
+bool isUserType(PyTypeObject* type)
+{
+ return checkType(type) && reinterpret_cast<SbkObjectType*>(type)->d->is_user_type;
+}
+
+bool canCallConstructor(PyTypeObject* myType, PyTypeObject* ctorType)
+{
+ FindBaseTypeVisitor visitor(ctorType);
+ walkThroughClassHierarchy(myType, &visitor);
+ if (!visitor.found()) {
+ PyErr_Format(PyExc_TypeError, "%s isn't a direct base class of %s", ctorType->tp_name, myType->tp_name);
+ return false;
+ }
+ return true;
+}
+
+
+bool hasExternalCppConversions(SbkObjectType*) { return false; } // DEPRECATED.
+bool isExternalConvertible(SbkObjectType *, PyObject *) { return false; } // DEPRECATED.
+void setExternalCppConversionFunction(SbkObjectType*, ExtendedToCppFunc) {} // DEPRECATED.
+void setExternalIsConvertibleFunction(SbkObjectType*, ExtendedIsConvertibleFunc) {} // DEPRECATED.
+void* callExternalCppConversion(SbkObjectType*, PyObject*) { return 0; } // DEPRECATED.
+
+
+bool hasCast(SbkObjectType* type)
+{
+ return type->d->mi_specialcast;
+}
+
+void* cast(SbkObjectType* sourceType, SbkObject* obj, PyTypeObject* targetType)
+{
+ return sourceType->d->mi_specialcast(Object::cppPointer(obj, targetType), reinterpret_cast<SbkObjectType*>(targetType));
+}
+
+void setCastFunction(SbkObjectType* type, SpecialCastFunction func)
+{
+ type->d->mi_specialcast = func;
+}
+
+void setOriginalName(SbkObjectType* self, const char* name)
+{
+ if (self->d->original_name)
+ free(self->d->original_name);
+ self->d->original_name = strdup(name);
+}
+
+const char* getOriginalName(SbkObjectType* self)
+{
+ return self->d->original_name;
+}
+
+void setTypeDiscoveryFunctionV2(SbkObjectType* self, TypeDiscoveryFuncV2 func)
+{
+ self->d->type_discovery = func;
+}
+
+void setTypeDiscoveryFunction(SbkObjectType* self, TypeDiscoveryFunc func)
+{
+ self->d->type_discovery = (TypeDiscoveryFuncV2)func;
+}
+
+TypeDiscoveryFunc getTypeDiscoveryFunction(SbkObjectType* self)
+{
+ // This is an illegal cast because the return value is different,
+ // but nobody ever used this function, so... =]
+ return (TypeDiscoveryFunc)self->d->type_discovery;
+}
+
+void copyMultimpleheritance(SbkObjectType* self, SbkObjectType* other)
+{
+ self->d->mi_init = other->d->mi_init;
+ self->d->mi_offsets = other->d->mi_offsets;
+ self->d->mi_specialcast = other->d->mi_specialcast;
+}
+
+void setMultipleIheritanceFunction(SbkObjectType* self, MultipleInheritanceInitFunction function)
+{
+ self->d->mi_init = function;
+}
+
+MultipleInheritanceInitFunction getMultipleIheritanceFunction(SbkObjectType* self)
+{
+ return self->d->mi_init;
+}
+
+void setDestructorFunction(SbkObjectType* self, ObjectDestructor func)
+{
+ self->d->cpp_dtor = func;
+}
+
+void initPrivateData(SbkObjectType* self)
+{
+ self->d = new SbkObjectTypePrivate;
+ memset(self->d, 0, sizeof(SbkObjectTypePrivate));
+}
+
+bool introduceWrapperType(PyObject* enclosingObject,
+ const char* typeName, const char* originalName,
+ SbkObjectType* type, ObjectDestructor cppObjDtor,
+ SbkObjectType* baseType, PyObject* baseTypes,
+ bool isInnerClass)
+{
+ initPrivateData(type);
+ setOriginalName(type, originalName);
+ setDestructorFunction(type, cppObjDtor);
+
+ if (baseType) {
+ type->super.ht_type.tp_base = reinterpret_cast<PyTypeObject *>(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);
+ type->super.ht_type.tp_bases = baseTypes;
+ } else {
+ BindingManager::instance().addClassInheritance(baseType, type);
+ }
+ }
+
+ if (PyType_Ready(reinterpret_cast<PyTypeObject *>(type)) < 0)
+ return false;
+
+ if (isInnerClass)
+ return PyDict_SetItemString(enclosingObject, typeName, reinterpret_cast<PyObject *>(type)) == 0;
+
+ //PyModule_AddObject steals type's reference.
+ Py_INCREF(reinterpret_cast<PyObject *>(type));
+ return PyModule_AddObject(enclosingObject, typeName, reinterpret_cast<PyObject *>(type)) == 0;
+}
+
+void setSubTypeInitHook(SbkObjectType* self, SubTypeInitHook func)
+{
+ self->d->subtype_init = func;
+}
+
+void* getTypeUserData(SbkObjectType* self)
+{
+ return self->d->user_data;
+}
+
+void setTypeUserData(SbkObjectType* self, void* userData, DeleteUserDataFunc d_func)
+{
+ self->d->user_data = userData;
+ self->d->d_func = d_func;
+}
+
+} // namespace ObjectType
+
+
+namespace Object
+{
+
+static void recursive_invalidate(SbkObject* self, std::set<SbkObject*>& seen);
+
+bool checkType(PyObject* pyObj)
+{
+ return ObjectType::checkType(pyObj->ob_type);
+}
+
+bool isUserType(PyObject* pyObj)
+{
+ return ObjectType::isUserType(pyObj->ob_type);
+}
+
+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)
+{
+ if (PySequence_Check(pyObj)) {
+ std::list<SbkObject*> objs = splitPyObject(pyObj);
+ std::list<SbkObject*>::const_iterator it = objs.begin();
+ for(; it != objs.end(); ++it) {
+ if (owner)
+ getOwnership(*it);
+ else
+ releaseOwnership(*it);
+ }
+ } 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)
+{
+ SbkObjectType* sbkType = reinterpret_cast<SbkObjectType*>(Py_TYPE(pyObj));
+ if (sbkType->d->is_multicpp) {
+ Shiboken::DtorCallerVisitor visitor(pyObj);
+ Shiboken::walkThroughClassHierarchy(Py_TYPE(pyObj), &visitor);
+ } else {
+ Shiboken::ThreadStateSaver threadSaver;
+ threadSaver.save();
+ sbkType->d->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 = 0;
+ 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++
+ SbkObjectType* selfType = reinterpret_cast<SbkObjectType*>(Py_TYPE(self));
+ if (!self->d->hasOwnership || Shiboken::Conversions::pythonTypeIsValueType(selfType->d->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)
+{
+ std::list<SbkObject*> objs = splitPyObject(pyobj);
+ std::list<SbkObject*>::const_iterator it = objs.begin();
+ for (; it != objs.end(); it++)
+ recursive_invalidate(*it, 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;
+ ChildrenList::iterator it = copy.begin();
+
+ for (; it != copy.end(); ++it) {
+ // invalidate the child
+ recursive_invalidate(*it, 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(*it, true, true);
+ }
+ }
+
+ // If has ref to other objects invalidate all
+ if (self->d->referredObjects) {
+ RefCountMap& refCountMap = *(self->d->referredObjects);
+ RefCountMap::iterator iter;
+ for (iter = refCountMap.begin(); iter != refCountMap.end(); ++iter) {
+ const std::list<PyObject*> lst = iter->second;
+ std::list<PyObject*>::const_iterator it = lst.begin();
+ while(it != lst.end()) {
+ recursive_invalidate(*it, seen);
+ ++it;
+ }
+ }
+ }
+}
+
+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) {
+ ChildrenList::iterator it = self->d->parentInfo->children.begin();
+ for (; it != self->d->parentInfo->children.end(); ++it)
+ makeValid(*it);
+ }
+
+ // If has ref to other objects make all valid again
+ if (self->d->referredObjects) {
+ RefCountMap& refCountMap = *(self->d->referredObjects);
+ RefCountMap::iterator iter;
+ for (iter = refCountMap.begin(); iter != refCountMap.end(); ++iter) {
+ const std::list<PyObject*> lst = iter->second;
+ std::list<PyObject*>::const_iterator it = lst.begin();
+ while(it != lst.end()) {
+ if (Shiboken::Object::checkType(*it))
+ makeValid(reinterpret_cast<SbkObject*>(*it));
+ ++it;
+ }
+ }
+ }
+}
+
+bool hasParentInfo(SbkObject* pyObj)
+{
+ return pyObj->d->parentInfo;
+}
+
+void* cppPointer(SbkObject* pyObj, PyTypeObject* desiredType)
+{
+ PyTypeObject* type = Py_TYPE(pyObj);
+ int idx = 0;
+ if (reinterpret_cast<SbkObjectType*>(type)->d->is_multicpp)
+ idx = getTypeIndexOnHierarchy(type, desiredType);
+ if (pyObj->d->cptr)
+ return pyObj->d->cptr[idx];
+ return 0;
+}
+
+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;
+ if (reinterpret_cast<SbkObjectType*>(Py_TYPE(sbkObj))->d->is_multicpp)
+ idx = getTypeIndexOnHierarchy(Py_TYPE(sbkObj), desiredType);
+
+ bool alreadyInitialized = sbkObj->d->cptr[idx];
+ 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(pyObj->ob_type) != &SbkObjectType_Type) {
+ return true;
+ }
+
+ SbkObjectPrivate* 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.", pyObj->ob_type->tp_name);
+ return false;
+ }
+
+ if (!priv->validCppObject) {
+ PyErr_Format(PyExc_RuntimeError, "Internal C++ object (%s) already deleted.", pyObj->ob_type->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(pyObj->ob_type, reinterpret_cast<PyTypeObject*>(&SbkObject_Type))) {
+ 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 0;
+
+ ParentInfo* pInfo = wrapper->d->parentInfo;
+ if (!pInfo)
+ return 0;
+
+ ChildrenList& children = pInfo->children;
+
+ ChildrenList::iterator childrenEnd = children.end();
+ for (ChildrenList::iterator iChild = children.begin(); iChild != childrenEnd; ++iChild) {
+ if (!((*iChild)->d && (*iChild)->d->cptr))
+ continue;
+ if ((*iChild)->d->cptr[0] == wrapper->d->cptr[0]) {
+ if (reinterpret_cast<const void *>(Py_TYPE(*iChild)) == reinterpret_cast<const void *>(instanceType))
+ return const_cast<SbkObject *>((*iChild));
+ else
+ return findColocatedChild(const_cast<SbkObject *>(*iChild), instanceType);
+ }
+ }
+ return 0;
+}
+
+
+PyObject *newObject(SbkObjectType* instanceType,
+ void* cptr,
+ bool hasOwnership,
+ bool isExactType,
+ const char* typeName)
+{
+ // Try to find the exact type of cptr.
+ if (!isExactType) {
+ PyTypeObject* exactType = 0;
+ if (typeName) {
+ exactType = Shiboken::Conversions::getPythonTypeObject(typeName);
+ if (exactType)
+ instanceType = reinterpret_cast<SbkObjectType*>(exactType);
+ }
+ if (!exactType)
+ instanceType = BindingManager::instance().resolveType(&cptr, instanceType);
+ }
+
+ bool shouldCreate = true;
+ bool shouldRegister = true;
+ SbkObject* self = 0;
+
+ // 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), 0, 0));
+ 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, 0);
+}
+
+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 = 0;
+ }
+
+ // 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
+ ChildrenList::iterator iChild = std::find(oldBrothers.begin(), oldBrothers.end(), child);
+ if (iChild == oldBrothers.end())
+ return;
+
+ oldBrothers.erase(iChild);
+
+ pInfo->parent = 0;
+
+ // 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, 0));
+ 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;
+ SbkObject* parent_ = reinterpret_cast<SbkObject*>(parent);
+ SbkObject* 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 = 0;
+ // delete self->d; PYSIDE-205: wrong!
+ }
+ delete self->d; // PYSIDE-205: always delete d.
+ Py_XDECREF(self->ob_dict);
+ Py_TYPE(self)->tp_free(self);
+}
+
+void setTypeUserData(SbkObject* wrapper, void* userData, DeleteUserDataFunc d_func)
+{
+ SbkObjectType* ob_type = reinterpret_cast<SbkObjectType*>(Py_TYPE(wrapper));
+ if (ob_type->d->user_data)
+ ob_type->d->d_func(ob_type->d->user_data);
+
+ ob_type->d->d_func = d_func;
+ ob_type->d->user_data = userData;
+}
+
+void* getTypeUserData(SbkObject* wrapper)
+{
+ return reinterpret_cast<SbkObjectType*>(Py_TYPE(wrapper))->d->user_data;
+}
+
+void keepReference(SbkObject* self, const char* key, PyObject* referredObject, bool append)
+{
+ bool isNone = (!referredObject || (referredObject == Py_None));
+
+ if (!self->d->referredObjects)
+ self->d->referredObjects = new Shiboken::RefCountMap;
+
+ RefCountMap& refCountMap = *(self->d->referredObjects);
+ RefCountMap::iterator iter = refCountMap.find(key);
+ std::list<PyObject*> objects;
+ if (iter != refCountMap.end()) {
+ objects = (*iter).second;
+ std::list<PyObject*>::const_iterator found = std::find(objects.begin(), objects.end(), referredObject);
+
+ // skip if objects already exists
+ if (found != objects.end())
+ return;
+ }
+
+ if (append && !isNone) {
+ refCountMap[key].push_back(referredObject);
+ Py_INCREF(referredObject);
+ } else if (!append) {
+ if (objects.size() > 0)
+ decRefPyObjectList(objects, isNone ? 0 : referredObject);
+ if (isNone) {
+ if (iter != refCountMap.end())
+ refCountMap.erase(iter);
+ } else {
+ objects.clear();
+ objects.push_back(referredObject);
+ refCountMap[key] = objects;
+ Py_INCREF(referredObject);
+ }
+ }
+}
+
+void removeReference(SbkObject* self, const char* key, PyObject* referredObject)
+{
+ if (!referredObject || (referredObject == Py_None))
+ return;
+
+ if (!self->d->referredObjects)
+ return;
+
+ RefCountMap& refCountMap = *(self->d->referredObjects);
+ RefCountMap::iterator iter = refCountMap.find(key);
+ if (iter != refCountMap.end()) {
+ decRefPyObjectList(iter->second);
+ refCountMap.erase(iter);
+ }
+}
+
+void clearReferences(SbkObject* self)
+{
+ if (!self->d->referredObjects)
+ return;
+
+ RefCountMap& refCountMap = *(self->d->referredObjects);
+ RefCountMap::iterator iter;
+ for (iter = refCountMap.begin(); iter != refCountMap.end(); ++iter)
+ decRefPyObjectList(iter->second);
+ self->d->referredObjects->clear();
+}
+
+std::string info(SbkObject* self)
+{
+ std::ostringstream s;
+ std::list<SbkObjectType*> bases;
+
+ if (self->d && self->d->cptr) {
+ if (ObjectType::isUserType(Py_TYPE(self)))
+ bases = getCppBaseClasses(Py_TYPE(self));
+ else
+ bases.push_back(reinterpret_cast<SbkObjectType*>(Py_TYPE(self)));
+
+ s << "C++ address....... ";
+ std::list<SbkObjectType*>::const_iterator it = bases.begin();
+ for (int i = 0; it != bases.end(); ++it, ++i)
+ s << reinterpret_cast<PyTypeObject *>(*it)->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.size()) {
+ s << "children.......... ";
+ ChildrenList& children = self->d->parentInfo->children;
+ for (ChildrenList::const_iterator it = children.begin(); it != children.end(); ++it) {
+ Shiboken::AutoDecRef child(PyObject_Str(reinterpret_cast<PyObject *>(*it)));
+ s << String::toCString(child) << ' ';
+ }
+ s << '\n';
+ }
+
+ if (self->d->referredObjects && self->d->referredObjects->size()) {
+ Shiboken::RefCountMap& map = *self->d->referredObjects;
+ s << "referred objects.. ";
+ Shiboken::RefCountMap::const_iterator it = map.begin();
+ for (; it != map.end(); ++it) {
+ if (it != map.begin())
+ s << " ";
+ s << '"' << it->first << "\" => ";
+ std::list<PyObject*>::const_iterator j = it->second.begin();
+ for (; j != it->second.end(); ++j) {
+ Shiboken::AutoDecRef obj(PyObject_Str(*j));
+ s << String::toCString(obj) << ' ';
+ }
+ s << ' ';
+ }
+ s << '\n';
+ }
+ return s.str();
+}
+
+} // namespace Object
+
+} // namespace Shiboken
diff --git a/sources/shiboken2/libshiboken/basewrapper.h b/sources/shiboken2/libshiboken/basewrapper.h
new file mode 100644
index 000000000..002337f3c
--- /dev/null
+++ b/sources/shiboken2/libshiboken/basewrapper.h
@@ -0,0 +1,451 @@
+/****************************************************************************
+**
+** Copyright (C) 2016 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$
+**
+****************************************************************************/
+
+#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 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_Type;
+extern LIBSHIBOKEN_API SbkObjectType SbkObject_Type;
+
+
+struct SbkObjectTypePrivate;
+/// PyTypeObject extended with C++ multiple inheritance information.
+struct LIBSHIBOKEN_API SbkObjectType
+{
+ PyHeapTypeObject super;
+ SbkObjectTypePrivate* d;
+};
+
+LIBSHIBOKEN_API PyObject* SbkObjectTpNew(PyTypeObject* subtype, 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));
+LIBSHIBOKEN_API void setErrorAboutWrongArguments(PyObject* args, const char* funcName, const char** cppOverloads);
+
+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);
+
+
+LIBSHIBOKEN_API bool hasExternalCppConversions(SbkObjectType*); // DEPRECATED.
+LIBSHIBOKEN_API bool isExternalConvertible(SbkObjectType*, PyObject*); // DEPRECATED.
+LIBSHIBOKEN_API void setExternalCppConversionFunction(SbkObjectType*, ExtendedToCppFunc); // DEPRECATED.
+LIBSHIBOKEN_API void setExternalIsConvertibleFunction(SbkObjectType*, ExtendedIsConvertibleFunc); // DEPRECATED.
+LIBSHIBOKEN_API void* callExternalCppConversion(SbkObjectType*, PyObject*); // DEPRECATED.
+
+
+/**
+ * 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 SBK_DEPRECATED(void setTypeDiscoveryFunction(SbkObjectType* self, TypeDiscoveryFunc func));
+LIBSHIBOKEN_API SBK_DEPRECATED(TypeDiscoveryFunc getTypeDiscoveryFunction(SbkObjectType* self));
+
+LIBSHIBOKEN_API void copyMultimpleheritance(SbkObjectType* self, SbkObjectType* other);
+LIBSHIBOKEN_API void setMultipleIheritanceFunction(SbkObjectType* self, MultipleInheritanceInitFunction func);
+LIBSHIBOKEN_API MultipleInheritanceInitFunction getMultipleIheritanceFunction(SbkObjectType* self);
+
+LIBSHIBOKEN_API void setDestructorFunction(SbkObjectType* self, ObjectDestructor func);
+
+LIBSHIBOKEN_API void initPrivateData(SbkObjectType* self);
+
+/**
+ * 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 bool introduceWrapperType(PyObject* enclosingObject,
+ const char* typeName, const char* originalName,
+ SbkObjectType* type, ObjectDestructor cppObjDtor = 0,
+ SbkObjectType* baseType = 0, PyObject* baseTypes = 0,
+ bool isInnerClass = false);
+
+/**
+ * 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);
+
+}
+
+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 = 0);
+
+/**
+ * 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);
+
+/**
+ * Returns true if the pyObj holds information about their parents.
+ */
+LIBSHIBOKEN_API bool hasParentInfo(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);
+
+/**
+* \internal This is an internal function called by tp_dealloc, it's exported just for technical reasons.
+* \note Do not call this function inside your bindings.
+*/
+LIBSHIBOKEN_API void destroyParentInfo(SbkObject* obj, bool removeFromParent = true);
+
+/**
+ * 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
new file mode 100644
index 000000000..129322246
--- /dev/null
+++ b/sources/shiboken2/libshiboken/basewrapper_p.h
@@ -0,0 +1,287 @@
+/****************************************************************************
+**
+** Copyright (C) 2016 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$
+**
+****************************************************************************/
+
+#ifndef BASEWRAPPER_P_H
+#define BASEWRAPPER_P_H
+
+#include "sbkpython.h"
+#include "basewrapper.h"
+
+#include <list>
+#include <map>
+#include <set>
+#include <string>
+
+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.
+ */
+typedef std::map<std::string, std::list<PyObject*> > RefCountMap;
+
+/// Linked list of SbkBaseWrapper pointers
+typedef std::set<SbkObject*> ChildrenList;
+
+/// Structure used to store information about object parent and children.
+struct ParentInfo
+{
+ /// Default ctor.
+ ParentInfo() : parent(0), 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 = 0;
+ delete referredObjects;
+ referredObjects = 0;
+ }
+};
+
+// 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;
+ /// C++ name
+ char* original_name;
+ /// Type user data
+ void* user_data;
+ DeleteUserDataFunc d_func;
+ void (*subtype_init)(SbkObjectType*, PyObject*, PyObject*);
+};
+
+
+} // extern "C"
+
+namespace Shiboken
+{
+/**
+ * Utility function used to transform a PyObject that implements sequence protocol into a std::list.
+ **/
+std::list<SbkObject*> splitPyObject(PyObject* pyObj);
+
+/**
+* Visitor class used by walkOnClassHierarchy function.
+*/
+class HierarchyVisitor
+{
+public:
+ HierarchyVisitor() : m_wasFinished(false) {}
+ virtual ~HierarchyVisitor() {}
+ virtual void visit(SbkObjectType* node) = 0;
+ virtual void done() {}
+ void finish() { m_wasFinished = true; };
+ bool wasFinished() const { return m_wasFinished; }
+private:
+ bool m_wasFinished;
+};
+
+class BaseCountVisitor : public HierarchyVisitor
+{
+public:
+ BaseCountVisitor() : m_count(0) {}
+
+ void visit(SbkObjectType*)
+ {
+ m_count++;
+ }
+
+ int count() const { return m_count; }
+private:
+ int m_count;
+};
+
+class BaseAccumulatorVisitor : public HierarchyVisitor
+{
+public:
+ BaseAccumulatorVisitor() {}
+
+ void visit(SbkObjectType* node)
+ {
+ m_bases.push_back(node);
+ }
+
+ std::list<SbkObjectType*> bases() const { return m_bases; }
+private:
+ std::list<SbkObjectType*> m_bases;
+};
+
+class GetIndexVisitor : public HierarchyVisitor
+{
+public:
+ GetIndexVisitor(PyTypeObject* desiredType) : m_index(-1), m_desiredType(desiredType) {}
+ virtual void visit(SbkObjectType* node)
+ {
+ m_index++;
+ if (PyType_IsSubtype(reinterpret_cast<PyTypeObject*>(node), m_desiredType))
+ finish();
+ }
+ int index() const { return m_index; }
+
+private:
+ int m_index;
+ PyTypeObject* m_desiredType;
+};
+
+/// Call the destructor of each C++ object held by a Python object
+class DtorCallerVisitor : public HierarchyVisitor
+{
+public:
+ DtorCallerVisitor(SbkObject* pyObj) : m_pyObj(pyObj) {}
+ void visit(SbkObjectType* node);
+ void done();
+protected:
+ std::list<std::pair<void*, SbkObjectType*> > m_ptrs;
+ SbkObject* m_pyObj;
+};
+
+/// Dealloc of each C++ object held by a Python object, this implies a call to the C++ object destructor
+class DeallocVisitor : public DtorCallerVisitor
+{
+public:
+ DeallocVisitor(SbkObject* pyObj) : DtorCallerVisitor(pyObj) {}
+ void done();
+};
+
+/// \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.
+*/
+void 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::list<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
new file mode 100644
index 000000000..d7e122cd7
--- /dev/null
+++ b/sources/shiboken2/libshiboken/bindingmanager.cpp
@@ -0,0 +1,344 @@
+/****************************************************************************
+**
+** Copyright (C) 2016 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$
+**
+****************************************************************************/
+
+#include "basewrapper.h"
+#include "basewrapper_p.h"
+#include "bindingmanager.h"
+#include "google/dense_hash_map"
+#include "sbkdbg.h"
+#include "gilstate.h"
+#include "sbkstring.h"
+#include "debugfreehook.h"
+
+#include <cstddef>
+#include <fstream>
+
+namespace Shiboken
+{
+
+typedef google::dense_hash_map<const void*, SbkObject*> WrapperMap;
+
+class Graph
+{
+public:
+ typedef std::list<SbkObjectType*> NodeList;
+ typedef google::dense_hash_map<SbkObjectType*, NodeList> Edges;
+
+ Edges m_edges;
+
+ Graph()
+ {
+ m_edges.set_empty_key(0);
+ }
+
+ 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";
+
+ Edges::const_iterator i = m_edges.begin();
+ for (; i != m_edges.end(); ++i) {
+ SbkObjectType* node1 = i->first;
+ const NodeList& nodeList = i->second;
+ NodeList::const_iterator j = nodeList.begin();
+ for (; j != nodeList.end(); ++j)
+ file << '"' << (*j)->super.ht_type.tp_name << "\" -> \"" << node1->super.ht_type.tp_name << "\"\n";
+ }
+ file << "}\n";
+ }
+#endif
+
+ SbkObjectType* identifyType(void** cptr, SbkObjectType* type, SbkObjectType* baseType) const
+ {
+ Edges::const_iterator edgesIt = m_edges.find(type);
+ if (edgesIt != m_edges.end()) {
+ const NodeList& adjNodes = m_edges.find(type)->second;
+ NodeList::const_iterator i = adjNodes.begin();
+ for (; i != adjNodes.end(); ++i) {
+ SbkObjectType* newType = identifyType(cptr, *i, baseType);
+ if (newType)
+ return newType;
+ }
+ }
+ void* typeFound = ((type->d && type->d->type_discovery) ? type->d->type_discovery(*cptr, baseType) : 0);
+ 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;
+ } else {
+ return 0;
+ }
+ }
+};
+
+
+#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());
+ WrapperMap::const_iterator iter;
+ for (iter = wrapperMap.begin(); iter != wrapperMap.end(); ++iter) {
+ const SbkObject *sbkObj = iter->second;
+ fprintf(stderr, "key: %p, value: %p (%s, refcnt: %d)\n", iter->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 {
+ WrapperMap wrapperMapper;
+ Graph classHierarchy;
+ 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.
+ WrapperMap::iterator iter = wrapperMapper.find(cptr);
+ if (iter != wrapperMapper.end() && (wrapper == 0 || iter->second == wrapper)) {
+ wrapperMapper.erase(iter);
+ return true;
+ }
+ return false;
+}
+
+void BindingManager::BindingManagerPrivate::assignWrapper(SbkObject* wrapper, const void* cptr)
+{
+ assert(cptr);
+ WrapperMap::iterator iter = wrapperMapper.find(cptr);
+ if (iter == wrapperMapper.end())
+ wrapperMapper.insert(std::make_pair(cptr, wrapper));
+}
+
+BindingManager::BindingManager()
+{
+ m_d = new BindingManager::BindingManagerPrivate;
+ m_d->wrapperMapper.set_empty_key((WrapperMap::key_type)0);
+ m_d->wrapperMapper.set_deleted_key((WrapperMap::key_type)1);
+
+#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.size() == 0);
+ }
+ 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)
+{
+ SbkObjectType* instanceType = reinterpret_cast<SbkObjectType*>(Py_TYPE(pyObj));
+ SbkObjectTypePrivate* d = instanceType->d;
+
+ 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*>((std::size_t) cptr + (*offset)));
+ offset++;
+ }
+ }
+}
+
+void BindingManager::releaseWrapper(SbkObject* sbkObj)
+{
+ SbkObjectType* sbkType = reinterpret_cast<SbkObjectType*>(Py_TYPE(sbkObj));
+ SbkObjectTypePrivate* d = sbkType->d;
+ 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) {
+ unsigned char *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 *>((std::size_t) cptr + (*offset)), sbkObj);
+ offset++;
+ }
+ }
+ }
+ sbkObj->d->validCppObject = false;
+}
+
+SbkObject* BindingManager::retrieveWrapper(const void* cptr)
+{
+ WrapperMap::iterator iter = m_d->wrapperMapper.find(cptr);
+ if (iter == m_d->wrapperMapper.end())
+ return 0;
+ 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 0;
+
+ 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)
+ && reinterpret_cast<PyMethodObject*>(method)->im_self == 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++) {
+ PyTypeObject* parent = reinterpret_cast<PyTypeObject*>(PyTuple_GET_ITEM(mro, i));
+ if (parent->tp_dict) {
+ defaultMethod = PyDict_GetItem(parent->tp_dict, pyMethodName);
+ if (defaultMethod && reinterpret_cast<PyMethodObject*>(method)->im_func != defaultMethod) {
+ Py_DECREF(pyMethodName);
+ return method;
+ }
+ }
+ }
+ }
+
+ Py_XDECREF(method);
+ Py_DECREF(pyMethodName);
+ return 0;
+}
+
+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;
+ WrapperMap::const_iterator 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 (WrapperMap::iterator 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
new file mode 100644
index 000000000..80c5add2f
--- /dev/null
+++ b/sources/shiboken2/libshiboken/bindingmanager.h
@@ -0,0 +1,109 @@
+/****************************************************************************
+**
+** Copyright (C) 2016 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$
+**
+****************************************************************************/
+
+#ifndef BINDINGMANAGER_H
+#define BINDINGMANAGER_H
+
+#include "sbkpython.h"
+#include <set>
+#include "shibokenmacros.h"
+
+struct SbkObject;
+struct SbkObjectType;
+
+namespace Shiboken
+{
+
+typedef void (*ObjectVisitor)(SbkObject*, void*);
+
+class LIBSHIBOKEN_API BindingManager
+{
+public:
+ static BindingManager& instance();
+
+ bool hasWrapper(const void *cptr);
+
+ void registerWrapper(SbkObject* pyObj, void* cptr);
+ void releaseWrapper(SbkObject* wrapper);
+
+ 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();
+ // disable copy
+ BindingManager();
+ BindingManager(const BindingManager&);
+ BindingManager& operator=(const BindingManager&);
+
+ struct BindingManagerPrivate;
+ BindingManagerPrivate* m_d;
+};
+
+} // namespace Shiboken
+
+#endif // BINDINGMANAGER_H
+
diff --git a/sources/shiboken2/libshiboken/conversions.h b/sources/shiboken2/libshiboken/conversions.h
new file mode 100644
index 000000000..f0af2be8e
--- /dev/null
+++ b/sources/shiboken2/libshiboken/conversions.h
@@ -0,0 +1,731 @@
+/****************************************************************************
+**
+** Copyright (C) 2016 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$
+**
+****************************************************************************/
+
+#ifndef CONVERSIONS_H
+#define CONVERSIONS_H
+
+#include "sbkpython.h"
+#include <limits>
+#include <typeinfo>
+
+#include "sbkstring.h"
+#include "sbkenum.h"
+#include "basewrapper.h"
+#include "bindingmanager.h"
+#include "sbkdbg.h"
+
+// 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))
+#include "autodecref.h"
+
+namespace Shiboken
+{
+/**
+* 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 0;
+}
+
+template<> inline PyTypeObject* SbkType<int>() { return &PyInt_Type; }
+template<> inline PyTypeObject* SbkType<unsigned int>() { return &PyLong_Type; }
+template<> inline PyTypeObject* SbkType<short>() { return &PyInt_Type; }
+template<> inline PyTypeObject* SbkType<unsigned short>() { return &PyInt_Type; }
+template<> inline PyTypeObject* SbkType<long>() { return &PyLong_Type; }
+template<> inline PyTypeObject* SbkType<unsigned long>() { return &PyLong_Type; }
+template<> inline PyTypeObject* SbkType<PY_LONG_LONG>() { return &PyLong_Type; }
+template<> inline PyTypeObject* SbkType<unsigned PY_LONG_LONG>() { return &PyLong_Type; }
+template<> inline PyTypeObject* SbkType<bool>() { return &PyBool_Type; }
+template<> inline PyTypeObject* SbkType<float>() { return &PyFloat_Type; }
+template<> inline PyTypeObject* SbkType<double>() { return &PyFloat_Type; }
+template<> inline PyTypeObject* SbkType<char>() { return &PyInt_Type; }
+template<> inline PyTypeObject* SbkType<signed char>() { return &PyInt_Type; }
+template<> inline PyTypeObject* SbkType<unsigned char>() { return &PyInt_Type; }
+
+/**
+ * Convenience template to create wrappers using the proper Python type for a given C++ class instance.
+ */
+template<typename T>
+inline PyObject* createWrapper(const T* cppobj, bool hasOwnership = false, bool isExactType = false)
+{
+ const char* typeName = 0;
+ if (!isExactType)
+ typeName = typeid(*const_cast<T*>(cppobj)).name();
+ return Object::newObject(reinterpret_cast<SbkObjectType*>(SbkType<T>()),
+ const_cast<T*>(cppobj), hasOwnership, isExactType, typeName);
+}
+
+// Base Conversions ----------------------------------------------------------
+// The basic converter must be empty to avoid object types being converted by value.
+template <typename T> struct Converter {};
+
+// Pointer conversion specialization for value types.
+template <typename T>
+struct Converter<T*>
+{
+ static inline bool checkType(PyObject* pyObj)
+ {
+ return Converter<T>::checkType(pyObj);
+ }
+
+ static inline bool isConvertible(PyObject* pyObj)
+ {
+ return pyObj == Py_None || PyObject_TypeCheck(pyObj, SbkType<T>());
+ }
+
+ static PyObject* toPython(const T* cppobj)
+ {
+ if (!cppobj)
+ Py_RETURN_NONE;
+ PyObject* pyobj = reinterpret_cast<PyObject*>(BindingManager::instance().retrieveWrapper(cppobj));
+ if (pyobj)
+ Py_INCREF(pyobj);
+ else
+ pyobj = createWrapper<T>(cppobj);
+ return pyobj;
+ }
+
+ static T* toCpp(PyObject* pyobj)
+ {
+ if (PyObject_TypeCheck(pyobj, SbkType<T>()))
+ return reinterpret_cast<T *>(Object::cppPointer(reinterpret_cast<SbkObject *>(pyobj), SbkType<T>()));
+ else if (Converter<T>::isConvertible(pyobj))
+ return new T(Converter<T>::toCpp(pyobj));
+ else if (pyobj == Py_None)
+ return 0;
+
+ assert(false);
+ return 0;
+ }
+};
+template <typename T> struct Converter<const T*> : Converter<T*> {};
+
+// Specialization for reference conversions.
+template <typename T>
+struct Converter<T&>
+{
+ static inline bool checkType(PyObject* pyObj) { return Converter<T>::checkType(pyObj); }
+ static inline bool isConvertible(PyObject* pyObj) { return Converter<T>::isConvertible(pyObj); }
+ static inline PyObject* toPython(const T& cppobj) { return Converter<T*>::toPython(&cppobj); }
+ static inline T& toCpp(PyObject* pyobj) { return *Converter<T*>::toCpp(pyobj); }
+};
+
+// Void pointer conversions.
+template<>
+struct Converter<void*>
+{
+ static inline bool checkType(PyObject *) { return false; }
+ static inline bool isConvertible(PyObject *) { return true; }
+ static PyObject* toPython(void* cppobj)
+ {
+ if (!cppobj)
+ Py_RETURN_NONE;
+ PyObject *result = reinterpret_cast<PyObject *>(cppobj);
+ Py_INCREF(result);
+ return result;
+ }
+ static void* toCpp(PyObject* pyobj) { return pyobj; }
+};
+
+// Base converter meant to be inherited by converters for classes that could be
+// passed by value.
+// Example: "struct Converter<ValueTypeClass> : ValueTypeConverter<ValueTypeClass>"
+template <typename T>
+struct ValueTypeConverter
+{
+ static inline bool checkType(PyObject* pyObj) { return PyObject_TypeCheck(pyObj, SbkType<T>()); }
+
+ // The basic version of this method also tries to use the extended 'isConvertible' method.
+ static inline bool isConvertible(PyObject* pyobj)
+ {
+ if (PyObject_TypeCheck(pyobj, SbkType<T>()))
+ return true;
+ SbkObjectType* shiboType = reinterpret_cast<SbkObjectType*>(SbkType<T>());
+ return ObjectType::isExternalConvertible(shiboType, pyobj);
+ }
+ static inline PyObject* toPython(void* cppobj) { return toPython(*reinterpret_cast<T*>(cppobj)); }
+ static inline PyObject* toPython(const T& cppobj)
+ {
+ PyObject* obj = createWrapper<T>(new T(cppobj), true, true);
+// SbkBaseWrapper_setContainsCppWrapper(obj, SbkTypeInfo<T>::isCppWrapper);
+ return obj;
+ }
+ // Classes with implicit conversions are expected to reimplement 'toCpp' to build T from
+ // its various implicit constructors. Even classes without implicit conversions could
+ // get some of those via other modules defining conversion operator for them, thus
+ // the basic Converter for value types checks for extended conversion and tries to
+ // use them if it is the case.
+ static inline T toCpp(PyObject* pyobj)
+ {
+ if (!PyObject_TypeCheck(pyobj, SbkType<T>())) {
+ SbkObjectType* shiboType = reinterpret_cast<SbkObjectType*>(SbkType<T>());
+ if (ObjectType::hasExternalCppConversions(shiboType) && isConvertible(pyobj)) {
+ T* cptr = reinterpret_cast<T*>(ObjectType::callExternalCppConversion(shiboType, pyobj));
+ const T result = *cptr;
+ delete cptr;
+ return result;
+ }
+ assert(false);
+ }
+ return *reinterpret_cast<T*>(Object::cppPointer(reinterpret_cast<SbkObject*>(pyobj), SbkType<T>()));
+ }
+};
+
+// Base converter meant to be inherited by converters for abstract classes and object types
+// (i.e. classes with private copy constructors and = operators).
+// Example: "struct Converter<AbstractClass*> : ObjectTypeConverter<AbstractClass>"
+template <typename T>
+struct ObjectTypeConverter
+{
+ static inline bool checkType(PyObject* pyObj) { return pyObj == Py_None || PyObject_TypeCheck(pyObj, SbkType<T>()); }
+ /// Py_None objects are the only objects convertible to an object type (in the form of a NULL pointer).
+ static inline bool isConvertible(PyObject* pyObj) { return pyObj == Py_None || PyObject_TypeCheck(pyObj, SbkType<T>()); }
+ /// Convenience overload that calls "toPython(const T*)" method.
+ static inline PyObject* toPython(void* cppobj) { return toPython(reinterpret_cast<T*>(cppobj)); }
+ /// Returns a new Python wrapper for the C++ object or an existing one with its reference counter incremented.
+ static PyObject* toPython(const T* cppobj)
+ {
+ if (!cppobj)
+ Py_RETURN_NONE;
+ PyObject* pyobj = reinterpret_cast<PyObject*>(BindingManager::instance().retrieveWrapper(cppobj));
+ if (pyobj)
+ Py_INCREF(pyobj);
+ else
+ pyobj = createWrapper<T>(cppobj);
+ return pyobj;
+ }
+ /// Returns the wrapped C++ pointer casted properly, or a NULL pointer if the argument is a Py_None.
+ static T* toCpp(PyObject* pyobj)
+ {
+ if (pyobj == Py_None)
+ return 0;
+ SbkObject *sbkObj = reinterpret_cast<SbkObject *>(pyobj);
+ SbkObjectType* shiboType = reinterpret_cast<SbkObjectType*>(pyobj->ob_type);
+ if (ObjectType::hasCast(shiboType))
+ return reinterpret_cast<T*>(ObjectType::cast(shiboType, sbkObj, SbkType<T>()));
+ return reinterpret_cast<T *>(Object::cppPointer(sbkObj, SbkType<T>()));
+ }
+};
+
+template <typename T>
+struct ObjectTypeReferenceConverter : ObjectTypeConverter<T>
+{
+ static inline bool checkType(PyObject* pyObj) { return PyObject_TypeCheck(pyObj, SbkType<T>()); }
+ static inline bool isConvertible(PyObject* pyObj) { return PyObject_TypeCheck(pyObj, SbkType<T>()); }
+ static inline PyObject* toPython(const T& cppobj) { return Converter<T*>::toPython(&cppobj); }
+ static inline T& toCpp(PyObject* pyobj)
+ {
+ T* t = Converter<T*>::toCpp(pyobj);
+ assert(t);
+ return *t;
+ }
+};
+
+// PyObject* specialization to avoid converting what doesn't need to be converted.
+template<>
+struct Converter<PyObject*> : ObjectTypeConverter<PyObject*>
+{
+ static inline PyObject* toCpp(PyObject* pyobj) { return pyobj; }
+};
+
+// Primitive Conversions ------------------------------------------------------
+template <>
+struct Converter<bool>
+{
+ static inline bool checkType(PyObject* pyobj) { return PyBool_Check(pyobj); }
+ static inline bool isConvertible(PyObject* pyobj) { return PyInt_Check(pyobj); }
+ static inline PyObject* toPython(void* cppobj) { return toPython(*reinterpret_cast<bool*>(cppobj)); }
+ static inline PyObject* toPython(bool cppobj) { return PyBool_FromLong(cppobj); }
+ static inline bool toCpp(PyObject* pyobj) { return PyInt_AS_LONG(pyobj); }
+};
+
+/**
+ * Helper template for checking if a value overflows when casted to type T
+ */
+template<typename T, bool isSigned = std::numeric_limits<T>::is_signed >
+struct OverFlowChecker;
+
+template<typename T>
+struct OverFlowChecker<T, true>
+{
+ static bool check(const PY_LONG_LONG& value)
+ {
+ return value < std::numeric_limits<T>::min() || value > std::numeric_limits<T>::max();
+ }
+};
+
+template<typename T>
+struct OverFlowChecker<T, false>
+{
+ static bool check(const PY_LONG_LONG& value)
+ {
+ return value < 0 || static_cast<unsigned long long>(value) > std::numeric_limits<T>::max();
+ }
+};
+
+template<>
+struct OverFlowChecker<PY_LONG_LONG, true>
+{
+ static bool check(const PY_LONG_LONG &)
+ {
+ return false;
+ }
+};
+
+template<>
+struct OverFlowChecker<double, true>
+{
+ static bool check(const double &)
+ {
+ return false;
+ }
+};
+
+template<>
+struct OverFlowChecker<float, true>
+{
+ static bool check(const double& value)
+ {
+ return value < std::numeric_limits<float>::min() || value > std::numeric_limits<float>::max();
+ }
+};
+
+template <typename PyIntEquiv>
+struct Converter_PyInt
+{
+ static inline bool checkType(PyObject* pyobj) { return PyInt_Check(pyobj); }
+ static inline bool isConvertible(PyObject* pyobj) { return SbkNumber_Check(pyobj); }
+ static inline PyObject* toPython(void* cppobj) { return toPython(*reinterpret_cast<PyIntEquiv*>(cppobj)); }
+ static inline PyObject* toPython(const PyIntEquiv& cppobj) { return PyInt_FromLong((long) cppobj); }
+ static PyIntEquiv toCpp(PyObject* pyobj)
+ {
+ if (PyFloat_Check(pyobj)) {
+ double d_result = PyFloat_AS_DOUBLE(pyobj);
+ // If cast to long directly it could overflow silently
+ if (OverFlowChecker<PyIntEquiv>::check(d_result))
+ PyErr_SetObject(PyExc_OverflowError, 0);
+ return static_cast<PyIntEquiv>(d_result);
+ } else {
+ PY_LONG_LONG result = PyLong_AsLongLong(pyobj);
+ if (OverFlowChecker<PyIntEquiv>::check(result))
+ PyErr_SetObject(PyExc_OverflowError, 0);
+ return static_cast<PyIntEquiv>(result);
+ }
+ }
+};
+
+template <typename T>
+struct Converter_PyULongInt : Converter_PyInt<T>
+{
+ static inline PyObject* toPython(void* cppobj) { return toPython(*reinterpret_cast<T*>(cppobj)); }
+ static inline PyObject* toPython(const T& cppobj) { return PyLong_FromUnsignedLong(cppobj); }
+};
+
+/// Specialization to convert char and unsigned char, it accepts Python numbers and strings with just one character.
+template <typename CharType>
+struct CharConverter
+{
+ static inline bool checkType(PyObject* pyobj) { return SbkChar_Check(pyobj); }
+ static inline bool isConvertible(PyObject* pyobj) { return SbkChar_Check(pyobj); }
+ static inline PyObject* toPython(void* cppobj) { return toPython(*reinterpret_cast<CharType*>(cppobj)); }
+ static inline PyObject* toPython(const CharType& cppobj) { return PyInt_FromLong(cppobj); }
+ static CharType toCpp(PyObject* pyobj)
+ {
+ if (PyBytes_Check(pyobj)) {
+ assert(PyBytes_GET_SIZE(pyobj) == 1); // This check is made on SbkChar_Check
+ return PyBytes_AS_STRING(pyobj)[0];
+ } else if (PyInt_Check(pyobj)) {
+ PY_LONG_LONG result = PyInt_AsUnsignedLongLongMask(pyobj);
+ if (OverFlowChecker<CharType>::check(result))
+ PyErr_SetObject(PyExc_OverflowError, 0);
+ return result;
+ } else if (Shiboken::String::check(pyobj)) {
+ return Shiboken::String::toCString(pyobj)[0];
+ } else {
+ return 0;
+ }
+ }
+};
+
+template <> struct Converter<unsigned long> : Converter_PyULongInt<unsigned long> {};
+template <> struct Converter<unsigned int> : Converter_PyULongInt<unsigned int> {};
+template <> struct Converter<char> : CharConverter<char>
+{
+ // Should we really return a string?
+ using CharConverter<char>::toPython;
+ using CharConverter<char>::isConvertible;
+ using CharConverter<char>::toCpp;
+
+
+ static inline bool isConvertible(PyObject* pyobj) {
+ return SbkChar_Check(pyobj);
+ }
+
+ static inline PyObject* toPython(const char& cppObj) {
+ return Shiboken::String::fromFormat("%c", cppObj);
+ }
+
+ static char toCpp(PyObject* pyobj)
+ {
+ if (PyBytes_Check(pyobj)) {
+ assert(PyBytes_GET_SIZE(pyobj) == 1); // This check is made on SbkChar_Check
+ return PyBytes_AS_STRING(pyobj)[0];
+ } else if (PyInt_Check(pyobj)) {
+ PY_LONG_LONG result = PyInt_AsUnsignedLongLongMask(pyobj);
+ if (OverFlowChecker<char>::check(result))
+ PyErr_SetObject(PyExc_OverflowError, 0);
+ return char(result);
+ } else if (Shiboken::String::check(pyobj)) {
+ return Shiboken::String::toCString(pyobj)[0];
+ } else {
+ return 0;
+ }
+ }
+};
+template <> struct Converter<signed char> : CharConverter<signed char> {};
+template <> struct Converter<unsigned char> : CharConverter<unsigned char> {};
+template <> struct Converter<int> : Converter_PyInt<int> {};
+template <> struct Converter<short> : Converter_PyInt<short> {};
+template <> struct Converter<unsigned short> : Converter_PyInt<unsigned short> {};
+template <> struct Converter<long> : Converter_PyInt<long> {};
+
+template <>
+struct Converter<PY_LONG_LONG>
+{
+ static inline PyObject* toPython(void* cppobj) { return toPython(*reinterpret_cast<PY_LONG_LONG*>(cppobj)); }
+ static inline PyObject* toPython(PY_LONG_LONG cppobj) { return PyLong_FromLongLong(cppobj); }
+ static inline PY_LONG_LONG toCpp(PyObject* pyobj) { return (PY_LONG_LONG) PyLong_AsLongLong(pyobj); }
+};
+
+template <>
+struct Converter<unsigned PY_LONG_LONG>
+{
+ static inline PyObject* toPython(void* cppobj)
+ {
+ return toPython(*reinterpret_cast<unsigned PY_LONG_LONG*>(cppobj));
+ }
+ static inline PyObject* toPython(unsigned PY_LONG_LONG cppobj)
+ {
+ return PyLong_FromUnsignedLongLong(cppobj);
+ }
+ static inline unsigned PY_LONG_LONG toCpp(PyObject* pyobj)
+ {
+#if PY_MAJOR_VERSION >= 3
+ if (!PyLong_Check(pyobj)) {
+ PyErr_SetString(PyExc_TypeError, "Invalid type for unsigned long long conversion");
+ return 0;
+ }
+
+ return PyLong_AsUnsignedLongLong(pyobj);
+#else
+ if (PyInt_Check(pyobj)) {
+ long result = (unsigned PY_LONG_LONG) PyInt_AsLong(pyobj);
+ if (result < 0) {
+ PyErr_SetObject(PyExc_OverflowError, 0);
+ return 0;
+ } else
+ return (unsigned PY_LONG_LONG) result;
+ } else if (PyLong_Check(pyobj)) {
+ return (unsigned PY_LONG_LONG) PyLong_AsUnsignedLongLong(pyobj);
+ } else {
+ PyErr_SetString(PyExc_TypeError, "Invalid type for unsigned long long conversion");
+ return 0;
+ }
+#endif // Python 2
+ }
+};
+
+template <typename PyFloatEquiv>
+struct Converter_PyFloat
+{
+ static inline bool checkType(PyObject* obj) { return PyFloat_Check(obj); }
+ static inline bool isConvertible(PyObject* obj) { return SbkNumber_Check(obj); }
+ static inline PyObject* toPython(void* cppobj) { return toPython(*reinterpret_cast<PyFloatEquiv*>(cppobj)); }
+ static inline PyObject* toPython(PyFloatEquiv cppobj) { return PyFloat_FromDouble((double) cppobj); }
+ static inline PyFloatEquiv toCpp(PyObject* pyobj)
+ {
+ if (PyInt_Check(pyobj) || PyLong_Check(pyobj))
+ return (PyFloatEquiv) PyLong_AsLong(pyobj);
+ return (PyFloatEquiv) PyFloat_AsDouble(pyobj);
+ }
+};
+
+template <> struct Converter<float> : Converter_PyFloat<float> {};
+template <> struct Converter<double> : Converter_PyFloat<double> {};
+
+// PyEnum Conversions ---------------------------------------------------------
+template <typename CppEnum>
+struct EnumConverter
+{
+ static inline bool checkType(PyObject* pyObj) { return PyObject_TypeCheck(pyObj, SbkType<CppEnum>()); }
+ static inline bool isConvertible(PyObject* pyObj) { return PyObject_TypeCheck(pyObj, SbkType<CppEnum>()); }
+ static inline PyObject* toPython(void* cppobj) { return toPython(*reinterpret_cast<CppEnum*>(cppobj)); }
+ static inline PyObject* toPython(CppEnum cppenum)
+ {
+ return Shiboken::Enum::newItem(Shiboken::SbkType<CppEnum>(), (long) cppenum);
+ }
+ static inline CppEnum toCpp(PyObject* pyObj)
+ {
+ return (CppEnum) Shiboken::Enum::getValue(pyObj);;
+ }
+};
+
+// C Sting Types --------------------------------------------------------------
+template <typename CString>
+struct Converter_CString
+{
+ // Note: 0 is also a const char* in C++, so None is accepted in checkType
+ static inline bool checkType(PyObject* pyObj) {
+ return Shiboken::String::check(pyObj);
+ }
+ static inline bool isConvertible(PyObject* pyObj) {
+ return Shiboken::String::isConvertible(pyObj);
+ }
+ static inline PyObject* toPython(void* cppobj) { return toPython(reinterpret_cast<CString>(cppobj)); }
+ static inline PyObject* toPython(CString cppobj)
+ {
+ if (!cppobj)
+ Py_RETURN_NONE;
+ return Shiboken::String::fromCString(cppobj);
+ }
+ static inline CString toCpp(PyObject* pyobj) {
+ if (pyobj == Py_None)
+ return 0;
+ return Shiboken::String::toCString(pyobj);
+ }
+};
+
+template <> struct Converter<const char*> : Converter_CString<const char*> {};
+
+template <> struct Converter<std::string> : Converter_CString<std::string>
+{
+ static inline PyObject* toPython(void* cppobj) { return toPython(*reinterpret_cast<std::string*>(cppobj)); }
+ static inline PyObject* toPython(std::string cppObj)
+ {
+ return Shiboken::String::fromCString(cppObj.c_str());
+ }
+
+ static inline std::string toCpp(PyObject* pyobj)
+ {
+ if (pyobj == Py_None)
+ return 0;
+ return std::string(Shiboken::String::toCString(pyobj));
+ }
+};
+
+// C++ containers -------------------------------------------------------------
+// The following container converters are meant to be used for pairs, lists and maps
+// that are similar to the STL containers of the same name.
+
+// For example to create a converter for a std::list the following code is enough:
+// template<typename T> struct Converter<std::list<T> > : StdListConverter<std::list<T> > {};
+
+// And this for a std::map:
+// template<typename KT, typename VT>
+// struct Converter<std::map<KT, VT> > : StdMapConverter<std::map<KT, VT> > {};
+
+template <typename StdList>
+struct StdListConverter
+{
+ static inline bool checkType(PyObject* pyObj)
+ {
+ return isConvertible(pyObj);
+ }
+
+ static inline bool isConvertible(PyObject* pyObj)
+ {
+ if (PyObject_TypeCheck(pyObj, SbkType<StdList>()))
+ return true;
+ // Sequence conversion are made ONLY for python sequences, not for
+ // binded types implementing sequence protocol, otherwise this will
+ // cause a mess like QBitArray being accepted by someone expecting a
+ // QStringList.
+ if ((SbkType<StdList>() && Object::checkType(pyObj)) || !PySequence_Check(pyObj))
+ return false;
+ for (int i = 0, max = PySequence_Length(pyObj); i < max; ++i) {
+ AutoDecRef item(PySequence_GetItem(pyObj, i));
+ if (!Converter<typename StdList::value_type>::isConvertible(item))
+ return false;
+ }
+ return true;
+ }
+ static PyObject* toPython(void* cppObj) { return toPython(*reinterpret_cast<StdList*>(cppObj)); }
+ static PyObject* toPython(const StdList& cppobj)
+ {
+ PyObject* result = PyList_New((int) cppobj.size());
+ typename StdList::const_iterator it = cppobj.begin();
+ for (int idx = 0; it != cppobj.end(); ++it, ++idx) {
+ typename StdList::value_type vh(*it);
+ PyList_SET_ITEM(result, idx, Converter<typename StdList::value_type>::toPython(vh));
+ }
+ return result;
+ }
+ static StdList toCpp(PyObject* pyobj)
+ {
+ if (PyObject_TypeCheck(pyobj, SbkType<StdList>()))
+ return *reinterpret_cast<StdList*>(Object::cppPointer(reinterpret_cast<SbkObject*>(pyobj), SbkType<StdList>()));
+
+ StdList result;
+ for (int i = 0; i < PySequence_Size(pyobj); i++) {
+ AutoDecRef pyItem(PySequence_GetItem(pyobj, i));
+ result.push_back(Converter<typename StdList::value_type>::toCpp(pyItem));
+ }
+ return result;
+ }
+};
+
+template <typename StdPair>
+struct StdPairConverter
+{
+ static inline bool checkType(PyObject* pyObj)
+ {
+ return isConvertible(pyObj);
+ }
+
+ static inline bool isConvertible(PyObject* pyObj)
+ {
+ if (PyObject_TypeCheck(pyObj, SbkType<StdPair>()))
+ return true;
+ if ((SbkType<StdPair>() && Object::checkType(pyObj)) || !PySequence_Check(pyObj) || PySequence_Length(pyObj) != 2)
+ return false;
+
+ AutoDecRef item1(PySequence_GetItem(pyObj, 0));
+ AutoDecRef item2(PySequence_GetItem(pyObj, 1));
+
+ if (!Converter<typename StdPair::first_type>::isConvertible(item1)
+ && !Converter<typename StdPair::second_type>::isConvertible(item2)) {
+ return false;
+ }
+ return true;
+ }
+ static PyObject* toPython(void* cppObj) { return toPython(*reinterpret_cast<StdPair*>(cppObj)); }
+ static PyObject* toPython(const StdPair& cppobj)
+ {
+ typename StdPair::first_type first(cppobj.first);
+ typename StdPair::second_type second(cppobj.second);
+ PyObject* tuple = PyTuple_New(2);
+ PyTuple_SET_ITEM(tuple, 0, Converter<typename StdPair::first_type>::toPython(first));
+ PyTuple_SET_ITEM(tuple, 1, Converter<typename StdPair::second_type>::toPython(second));
+ return tuple;
+ }
+ static StdPair toCpp(PyObject* pyobj)
+ {
+ StdPair result;
+ AutoDecRef pyFirst(PySequence_GetItem(pyobj, 0));
+ AutoDecRef pySecond(PySequence_GetItem(pyobj, 1));
+ result.first = Converter<typename StdPair::first_type>::toCpp(pyFirst);
+ result.second = Converter<typename StdPair::second_type>::toCpp(pySecond);
+ return result;
+ }
+};
+
+template <typename StdMap>
+struct StdMapConverter
+{
+ static inline bool checkType(PyObject* pyObj)
+ {
+ return isConvertible(pyObj);
+ }
+
+ static inline bool isConvertible(PyObject* pyObj)
+ {
+ if (PyObject_TypeCheck(pyObj, SbkType<StdMap>()))
+ return true;
+ if ((SbkType<StdMap>() && Object::checkType(pyObj)) || !PyDict_Check(pyObj))
+ return false;
+
+ PyObject* key;
+ PyObject* value;
+ Py_ssize_t pos = 0;
+
+ while (PyDict_Next(pyObj, &pos, &key, &value)) {
+ if (!Converter<typename StdMap::key_type>::isConvertible(key)
+ || !Converter<typename StdMap::mapped_type>::isConvertible(value)) {
+ return false;
+ }
+ }
+ return true;
+ }
+
+ static PyObject* toPython(void* cppObj) { return toPython(*reinterpret_cast<StdMap*>(cppObj)); }
+ static PyObject* toPython(const StdMap& cppobj)
+ {
+ PyObject* result = PyDict_New();
+ typename StdMap::const_iterator it = cppobj.begin();
+
+ for (; it != cppobj.end(); ++it) {
+ PyDict_SetItem(result,
+ Converter<typename StdMap::key_type>::toPython(it->first),
+ Converter<typename StdMap::mapped_type>::toPython(it->second));
+ }
+
+ return result;
+ }
+ static StdMap toCpp(PyObject* pyobj)
+ {
+ StdMap result;
+
+ PyObject* key;
+ PyObject* value;
+ Py_ssize_t pos = 0;
+
+ while (PyDict_Next(pyobj, &pos, &key, &value)) {
+ result.insert(typename StdMap::value_type(
+ Converter<typename StdMap::key_type>::toCpp(key),
+ Converter<typename StdMap::mapped_type>::toCpp(value)));
+ }
+ return result;
+ }
+};
+
+
+// class used to translate python objects to another type
+template <typename T> struct PythonConverter {};
+
+} // namespace Shiboken
+
+#endif // CONVERSIONS_H
+
diff --git a/sources/shiboken2/libshiboken/debugfreehook.cpp b/sources/shiboken2/libshiboken/debugfreehook.cpp
new file mode 100644
index 000000000..f5757a70f
--- /dev/null
+++ b/sources/shiboken2/libshiboken/debugfreehook.cpp
@@ -0,0 +1,194 @@
+/****************************************************************************
+**
+** Copyright (C) 2016 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$
+**
+****************************************************************************/
+
+#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
new file mode 100644
index 000000000..743d56e4c
--- /dev/null
+++ b/sources/shiboken2/libshiboken/debugfreehook.h
@@ -0,0 +1,61 @@
+/****************************************************************************
+**
+** Copyright (C) 2016 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$
+**
+****************************************************************************/
+
+#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/gilstate.cpp b/sources/shiboken2/libshiboken/gilstate.cpp
new file mode 100644
index 000000000..e7406fdd6
--- /dev/null
+++ b/sources/shiboken2/libshiboken/gilstate.cpp
@@ -0,0 +1,68 @@
+/****************************************************************************
+**
+** Copyright (C) 2016 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$
+**
+****************************************************************************/
+
+#include "gilstate.h"
+
+namespace Shiboken
+{
+
+GilState::GilState()
+ : m_locked(false)
+{
+ 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
new file mode 100644
index 000000000..e0f18a814
--- /dev/null
+++ b/sources/shiboken2/libshiboken/gilstate.h
@@ -0,0 +1,63 @@
+/****************************************************************************
+**
+** Copyright (C) 2016 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$
+**
+****************************************************************************/
+
+#ifndef GILSTATE_H
+#define GILSTATE_H
+
+#include <shibokenmacros.h>
+#include "sbkpython.h"
+
+namespace Shiboken
+{
+
+class LIBSHIBOKEN_API GilState
+{
+public:
+ GilState();
+ ~GilState();
+ void release();
+private:
+ PyGILState_STATE m_gstate;
+ bool m_locked;
+};
+
+} // namespace Shiboken
+
+#endif // GILSTATE_H
+
diff --git a/sources/shiboken2/libshiboken/helper.cpp b/sources/shiboken2/libshiboken/helper.cpp
new file mode 100644
index 000000000..9709d0776
--- /dev/null
+++ b/sources/shiboken2/libshiboken/helper.cpp
@@ -0,0 +1,142 @@
+/****************************************************************************
+**
+** Copyright (C) 2016 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$
+**
+****************************************************************************/
+
+#include "helper.h"
+#include <stdarg.h>
+
+namespace Shiboken
+{
+
+bool sequenceToArgcArgv(PyObject* argList, int* argc, char*** argv, const char* defaultAppName)
+{
+ if (!PySequence_Check(argList))
+ return false;
+
+ if (!defaultAppName)
+ defaultAppName = "PySideApplication";
+
+ // Check all items
+ Shiboken::AutoDecRef args(PySequence_Fast(argList, 0));
+ int numArgs = PySequence_Fast_GET_SIZE(argList);
+ for (int i = 0; i < numArgs; ++i) {
+ PyObject* item = PySequence_Fast_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 = PySequence_Fast_GET_ITEM(args.object(), i);
+ char* string = 0;
+ 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 0;
+
+ 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 0;
+ } else {
+ 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(NULL, 0, format, args) + 1;
+ char* 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;
+}
+
+} // namespace Shiboken
diff --git a/sources/shiboken2/libshiboken/helper.h b/sources/shiboken2/libshiboken/helper.h
new file mode 100644
index 000000000..f2061b667
--- /dev/null
+++ b/sources/shiboken2/libshiboken/helper.h
@@ -0,0 +1,136 @@
+/****************************************************************************
+**
+** Copyright (C) 2016 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$
+**
+****************************************************************************/
+
+#ifndef HELPER_H
+#define HELPER_H
+
+#include "sbkpython.h"
+#include "shibokenmacros.h"
+#include "conversions.h"
+#include "autodecref.h"
+
+#define SBK_UNUSED(x) (void)x;
+
+namespace Shiboken
+{
+
+template<typename A>
+inline PyObject* makeTuple(const A& a)
+{
+ return PyTuple_Pack(1, AutoDecRef(Converter<A>::toPython(a)).object());
+}
+
+template<typename A, typename B>
+inline PyObject* makeTuple(const A& a, const B& b)
+{
+ return PyTuple_Pack(2, AutoDecRef(Converter<A>::toPython(a)).object(),
+ AutoDecRef(Converter<B>::toPython(b)).object());
+}
+
+template<typename A, typename B, typename C>
+inline PyObject* makeTuple(const A& a, const B& b, const C& c)
+{
+ return PyTuple_Pack(3, AutoDecRef(Converter<A>::toPython(a)).object(),
+ AutoDecRef(Converter<B>::toPython(b)).object(),
+ AutoDecRef(Converter<C>::toPython(c)).object());
+}
+
+template<typename A, typename B, typename C, typename D>
+inline PyObject* makeTuple(const A& a, const B& b, const C& c, const D& d)
+{
+ return PyTuple_Pack(4, AutoDecRef(Converter<A>::toPython(a)).object(),
+ AutoDecRef(Converter<B>::toPython(b)).object(),
+ AutoDecRef(Converter<C>::toPython(c)).object(),
+ AutoDecRef(Converter<D>::toPython(d)).object());
+}
+
+template<typename A, typename B, typename C, typename D, typename E>
+inline PyObject* makeTuple(const A& a, const B& b, const C& c, const D& d, const E& e)
+{
+ return PyTuple_Pack(5, AutoDecRef(Converter<A>::toPython(a)).object(),
+ AutoDecRef(Converter<B>::toPython(b)).object(),
+ AutoDecRef(Converter<C>::toPython(c)).object(),
+ AutoDecRef(Converter<D>::toPython(d)).object(),
+ AutoDecRef(Converter<E>::toPython(e)).object());
+}
+
+/**
+* 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 sequenceToArgcArgv(PyObject* argList, int* argc, char*** argv, const char* defaultAppName = 0);
+
+/**
+ * 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(int size) { data = new T[size]; }
+ T& operator[](int pos) { return data[pos]; }
+ operator T*() const { return data; }
+ ~AutoArrayPointer() { delete[] data; }
+ private:
+ T* data;
+};
+
+/**
+ * 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/python25compat.h b/sources/shiboken2/libshiboken/python25compat.h
new file mode 100644
index 000000000..71c88d86a
--- /dev/null
+++ b/sources/shiboken2/libshiboken/python25compat.h
@@ -0,0 +1,104 @@
+/****************************************************************************
+**
+** Copyright (C) 2016 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$
+**
+****************************************************************************/
+
+#ifndef PYTHON25COMPAT_H
+#define PYTHON25COMPAT_H
+#include <Python.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/sbkconverter.cpp b/sources/shiboken2/libshiboken/sbkconverter.cpp
new file mode 100644
index 000000000..e7e9995b4
--- /dev/null
+++ b/sources/shiboken2/libshiboken/sbkconverter.cpp
@@ -0,0 +1,572 @@
+/****************************************************************************
+**
+** Copyright (C) 2016 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$
+**
+****************************************************************************/
+
+#include "sbkconverter.h"
+#include "sbkconverter_p.h"
+#include "basewrapper_p.h"
+#include "google/dense_hash_map"
+#include "autodecref.h"
+#include "sbkdbg.h"
+#include "helper.h"
+
+static SbkConverter** PrimitiveTypeConverters;
+
+typedef google::dense_hash_map<std::string, SbkConverter*> ConvertersMap;
+static ConvertersMap converters;
+
+namespace Shiboken {
+namespace Conversions {
+
+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(),
+ Primitive<void*>::createConverter()
+ };
+ PrimitiveTypeConverters = primitiveTypeConverters;
+
+ assert(converters.empty());
+ converters.set_empty_key("");
+ converters.set_deleted_key("?");
+ 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];
+}
+
+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;
+
+ 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);
+ type->d->converter = converter;
+ return converter;
+}
+
+SbkConverter* createConverter(PyTypeObject* type, CppToPythonFunc toPythonFunc)
+{
+ return createConverterObject(type, 0, 0, 0, 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(type->d->converter, pythonToCppFunc, isConvertibleToCppFunc);
+}
+
+PyObject* pointerToPython(const SbkObjectType *type, const void *cppIn)
+{
+ return pointerToPython(type->d->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(const SbkObjectType *type, const void *cppIn)
+{
+ return referenceToPython(type->d->converter, cppIn);
+}
+
+PyObject* referenceToPython(const SbkConverter *converter, const void *cppIn)
+{
+ assert(cppIn);
+
+ PyObject *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(const SbkObjectType *type, const void *cppIn)
+{
+ return CopyCppToPython(type->d->converter, cppIn);
+}
+PyObject* copyToPython(const SbkConverter *converter, const void *cppIn)
+{
+ return CopyCppToPython(converter, cppIn);
+}
+
+PythonToCppFunc isPythonToCppPointerConvertible(const SbkObjectType *type, PyObject *pyIn)
+{
+ assert(pyIn);
+ return type->d->converter->toCppPointerConversion.first(pyIn);
+}
+
+static inline PythonToCppFunc IsPythonToCppConvertible(const SbkConverter *converter, PyObject *pyIn)
+{
+ assert(pyIn);
+ const ToCppConversionList& convs = converter->toCppConversions;
+ for (ToCppConversionList::const_iterator conv = convs.begin(), end = convs.end(); conv != end; ++conv) {
+ PythonToCppFunc toCppFunc = 0;
+ if ((toCppFunc = (*conv).first(pyIn)))
+ return toCppFunc;
+ }
+ return 0;
+}
+PythonToCppFunc isPythonToCppValueConvertible(const SbkObjectType *type, PyObject *pyIn)
+{
+ return IsPythonToCppConvertible(type->d->converter, pyIn);
+}
+PythonToCppFunc isPythonToCppConvertible(const SbkConverter *converter, PyObject *pyIn)
+{
+ return IsPythonToCppConvertible(converter, pyIn);
+}
+
+PythonToCppFunc isPythonToCppReferenceConvertible(const 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);
+ *((void**)cppOut) = 0;
+}
+
+void* cppPointer(PyTypeObject* desiredType, SbkObject* pyIn)
+{
+ assert(pyIn);
+ if (!ObjectType::checkType(desiredType))
+ return pyIn;
+ SbkObjectType *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
+ ? 0
+ : 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
+ ? 0
+ : 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(const SbkObjectType *type, PyObject *pyIn, void *cppOut)
+{
+ assert(type);
+ _pythonToCppCopy(type->d->converter, pyIn, cppOut);
+}
+
+void pythonToCppCopy(const SbkConverter *converter, PyObject *pyIn, void *cppOut)
+{
+ _pythonToCppCopy(converter, pyIn, cppOut);
+}
+
+bool isImplicitConversion(const 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;
+}
+
+void registerConverterName(SbkConverter* converter , const char* typeName)
+{
+ ConvertersMap::iterator 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 0;
+}
+
+SbkConverter* primitiveTypeConverter(int index)
+{
+ return PrimitiveTypeConverters[index];
+}
+
+bool checkSequenceTypes(PyTypeObject* type, PyObject* pyIn)
+{
+ assert(type);
+ 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 (!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(const SbkObjectType *type, PyObject *pyIn)
+{
+ assert(type);
+ return convertibleSequenceTypes(type->d->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 0;
+}
+
+PyTypeObject* getPythonTypeObject(const char* typeName)
+{
+ return getPythonTypeObject(getConverter(typeName));
+}
+
+bool pythonTypeIsValueType(const SbkConverter *converter)
+{
+ assert(converter);
+ return converter->pointerToPython && converter->copyToPython;
+}
+
+bool pythonTypeIsObjectType(const SbkConverter *converter)
+{
+ return converter->pointerToPython && !converter->copyToPython;
+}
+
+bool pythonTypeIsWrapperType(const SbkConverter *converter)
+{
+ return converter->pointerToPython;
+}
+
+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, *((const void**)cppIn));
+ case ReferenceConversion:
+ return referenceToPython(m_converter, cppIn);
+ default:
+ PyErr_SetString(PyExc_RuntimeError, "tried to use invalid converter in 'C++ to Python' conversion");
+ }
+ return 0;
+}
+
+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
new file mode 100644
index 000000000..7489b930d
--- /dev/null
+++ b/sources/shiboken2/libshiboken/sbkconverter.h
@@ -0,0 +1,367 @@
+/****************************************************************************
+**
+** Copyright (C) 2016 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$
+**
+****************************************************************************/
+
+#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;
+
+/**
+ * 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 = 0);
+
+/**
+ * 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(const 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(const 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(const 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(const 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(const 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(const SbkObjectType *type, PyObject *pyIn);
+
+/// This is the same as isPythonToCppValueConvertible function.
+LIBSHIBOKEN_API PythonToCppFunc isPythonToCppConvertible(const SbkConverter *converter, 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(const 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(const 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(const 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
+
+template<typename T> SbkConverter* PrimitiveTypeConverter() { return 0; }
+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); }
+
+} } // namespace Shiboken::Conversions
+
+struct _SbkGenericType { PyHeapTypeObject super; SbkConverter** converter; };
+#define SBK_CONVERTER(pyType) (*reinterpret_cast<_SbkGenericType*>(pyType)->converter)
+
+
+#endif // SBK_CONVERTER_H
diff --git a/sources/shiboken2/libshiboken/sbkconverter_p.h b/sources/shiboken2/libshiboken/sbkconverter_p.h
new file mode 100644
index 000000000..b38561780
--- /dev/null
+++ b/sources/shiboken2/libshiboken/sbkconverter_p.h
@@ -0,0 +1,574 @@
+/****************************************************************************
+**
+** Copyright (C) 2016 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$
+**
+****************************************************************************/
+
+#ifndef SBK_CONVERTER_P_H
+#define SBK_CONVERTER_P_H
+
+#include "sbkpython.h"
+#include "sbkconverter.h"
+#include "sbkstring.h"
+#include <list>
+#include <limits>
+#include <typeinfo>
+#include <sstream>
+#include <iostream>
+
+#include "sbkdbg.h"
+
+extern "C"
+{
+
+typedef std::pair<IsConvertibleToCppFunc, PythonToCppFunc> ToCppConversion;
+typedef std::list<ToCppConversion> ToCppConversionList;
+
+/**
+ * \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.
+ */
+ ToCppConversionList toCppConversions;
+};
+
+} // extern "C"
+
+template<typename T, typename MaxLimitType, bool isSigned>
+struct OverFlowCheckerBase {
+ static void formatOverFlowMessage(const MaxLimitType& value,
+ const std::string *valueAsString = 0)
+ {
+ std::ostringstream str;
+ str << "libshiboken: Overflow: Value ";
+ if (valueAsString != 0 && !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> PyTypeObject* SbkType() { return 0; }
+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<const char*>() { return &PyString_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 <typename T> struct Primitive {};
+
+template <typename T>
+struct OnePrimitive
+{
+ static PyObject* toPython(const void*) { return 0; }
+ static PythonToCppFunc isConvertible(PyObject*) { return 0; }
+ static void toCpp(PyObject*, void*) {}
+ static SbkConverter* createConverter()
+ {
+ SbkConverter* converter = Shiboken::Conversions::createConverter(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 0; }
+ 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, 0);
+ *reinterpret_cast<INT * >(cppOut) = static_cast<INT>(result);
+ }
+ static PythonToCppFunc isConvertible(PyObject* pyIn)
+ {
+ if (PyFloat_Check(pyIn))
+ return toCpp;
+ return 0;
+ }
+ static void otherToCpp(PyObject* pyIn, void* cppOut)
+ {
+ PY_LONG_LONG result = PyLong_AsLongLong(pyIn);
+ if (OverFlowChecker<INT>::check(result, pyIn))
+ PyErr_SetObject(PyExc_OverflowError, 0);
+ *reinterpret_cast<INT * >(cppOut) = static_cast<INT>(result);
+ }
+ static PythonToCppFunc isOtherConvertible(PyObject* pyIn)
+ {
+ if (SbkNumber_Check(pyIn))
+ return otherToCpp;
+ return 0;
+ }
+};
+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(*((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 0;
+ }
+};
+
+template <>
+struct Primitive<unsigned PY_LONG_LONG> : OnePrimitive<unsigned PY_LONG_LONG>
+{
+ static PyObject* toPython(const void* cppIn)
+ {
+ return PyLong_FromUnsignedLongLong(*((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, 0);
+ *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 0;
+ }
+};
+
+// 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 0;
+ }
+ 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 0;
+ }
+};
+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 0;
+ }
+ 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 0;
+ }
+ static void otherToCpp(PyObject* pyIn, void* cppOut)
+ {
+ PY_LONG_LONG result = PyLong_AsLongLong(pyIn);
+ if (OverFlowChecker<CHAR>::check(result, pyIn))
+ PyErr_SetObject(PyExc_OverflowError, 0);
+ *reinterpret_cast<CHAR *>(cppOut) = CHAR(result);
+ }
+ static PythonToCppFunc isOtherConvertible(PyObject* pyIn)
+ {
+ if (SbkNumber_Check(pyIn))
+ return otherToCpp;
+ return 0;
+ }
+ 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((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((const char*)cppIn);
+ }
+ static void toCpp(PyObject *, void *cppOut)
+ {
+ *((const char**)cppOut) = 0;
+ }
+ static PythonToCppFunc isConvertible(PyObject* pyIn)
+ {
+ if (pyIn == Py_None)
+ return toCpp;
+ return 0;
+ }
+ static void otherToCpp(PyObject* pyIn, void* cppOut)
+ {
+ *((const char**)cppOut) = (const char*) Shiboken::String::toCString(pyIn);
+ }
+ static PythonToCppFunc isOtherConvertible(PyObject* pyIn)
+ {
+ if (Shiboken::String::check(pyIn))
+ return otherToCpp;
+ return 0;
+ }
+};
+
+template <>
+struct Primitive<std::string> : TwoPrimitive<std::string>
+{
+ static PyObject* toPython(const void* cppIn)
+ {
+ return Shiboken::String::fromCString(((std::string*)cppIn)->c_str());
+ }
+ static void toCpp(PyObject *, void *cppOut)
+ {
+ *((std::string*)cppOut) = std::string();
+ }
+ static PythonToCppFunc isConvertible(PyObject* pyIn)
+ {
+ if (pyIn == Py_None)
+ return toCpp;
+ return 0;
+ }
+ static void otherToCpp(PyObject* pyIn, void* cppOut)
+ {
+ *((std::string*)cppOut) = Shiboken::String::toCString(pyIn);
+ }
+ static PythonToCppFunc isOtherConvertible(PyObject* pyIn)
+ {
+ if (Shiboken::String::check(pyIn))
+ return otherToCpp;
+ return 0;
+ }
+};
+
+// Void pointer ----------------------------------------------------------------------------
+
+template <>
+struct Primitive<void*> : OnePrimitive<void*>
+{
+ static PyObject* toPython(const void* cppIn)
+ {
+ SbkDbg() << cppIn;
+ if (!cppIn)
+ Py_RETURN_NONE;
+ PyObject *result = reinterpret_cast<PyObject *>(const_cast<void *>(cppIn));
+ Py_INCREF(result);
+ return result;
+ }
+ static void toCpp(PyObject* pyIn, void* cppOut)
+ {
+ SbkDbg() << pyIn;
+ *reinterpret_cast<void **>(cppOut) = pyIn;
+ }
+ static PythonToCppFunc isConvertible(PyObject *)
+ {
+ return toCpp;
+ }
+};
+
+#endif // SBK_CONVERTER_P_H
diff --git a/sources/shiboken2/libshiboken/sbkdbg.h b/sources/shiboken2/libshiboken/sbkdbg.h
new file mode 100644
index 000000000..937153adf
--- /dev/null
+++ b/sources/shiboken2/libshiboken/sbkdbg.h
@@ -0,0 +1,124 @@
+/****************************************************************************
+**
+** Copyright (C) 2016 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$
+**
+****************************************************************************/
+
+#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(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
new file mode 100644
index 000000000..009d9ab2f
--- /dev/null
+++ b/sources/shiboken2/libshiboken/sbkenum.cpp
@@ -0,0 +1,623 @@
+/****************************************************************************
+**
+** Copyright (C) 2016 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$
+**
+****************************************************************************/
+
+#include "sbkenum.h"
+#include "sbkstring.h"
+#include "sbkconverter.h"
+#include "basewrapper.h"
+#include "sbkdbg.h"
+#include "autodecref.h"
+#include "typeresolver.h"
+#include "sbkpython.h"
+
+#include <string.h>
+#include <cstring>
+#include <list>
+
+#define SBK_ENUM(ENUM) reinterpret_cast<SbkEnumObject*>(ENUM)
+
+extern "C"
+{
+
+struct SbkEnumType
+{
+ PyHeapTypeObject super;
+ SbkConverter** converterPtr;
+ SbkConverter* converter;
+ const char* cppName;
+};
+
+struct SbkEnumObject
+{
+ PyObject_HEAD
+ long ob_value;
+ PyObject* ob_name;
+};
+
+static PyObject* SbkEnumObject_repr(PyObject* self)
+{
+ const SbkEnumObject *enumObj = reinterpret_cast<SbkEnumObject *>(self);
+ if (enumObj->ob_name)
+ return Shiboken::String::fromFormat("%s.%s", self->ob_type->tp_name, PyBytes_AS_STRING(enumObj->ob_name));
+ else
+ return Shiboken::String::fromFormat("%s(%ld)", self->ob_type->tp_name, enumObj->ob_value);
+}
+
+static int SbkEnumObject_print(PyObject* self, FILE* fp, int)
+{
+ Py_BEGIN_ALLOW_THREADS
+ const SbkEnumObject *enumObj = reinterpret_cast<SbkEnumObject *>(self);
+ if (enumObj->ob_name)
+ fprintf(fp, "%s.%s", self->ob_type->tp_name, PyBytes_AS_STRING(enumObj->ob_name));
+ else
+ fprintf(fp, "%s(%ld)", self->ob_type->tp_name, enumObj->ob_value);
+ Py_END_ALLOW_THREADS
+ return 0;
+}
+
+static PyObject* SbkEnumObject_name(PyObject* self, void*)
+{
+ SbkEnumObject *enum_self = reinterpret_cast<SbkEnumObject *>(self);
+
+ if (enum_self->ob_name == NULL)
+ 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 0;
+
+ SbkEnumObject* self = PyObject_New(SbkEnumObject, type);
+ if (!self)
+ return 0;
+ self->ob_value = itemValue;
+ PyObject* item = Shiboken::Enum::getEnumItemFromValue(type, itemValue);
+ if (item) {
+ self->ob_name = SbkEnumObject_name(item, 0);
+ Py_XDECREF(item);
+ } else {
+ self->ob_name = 0;
+ }
+ return reinterpret_cast<PyObject*>(self);
+}
+
+/* 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 long getNumberValue(PyObject* v)
+{
+ PyObject* number = PyNumber_Long(v);
+ long result = PyLong_AsLong(number);
+ Py_XDECREF(number);
+ return result;
+}
+
+static PyObject* enum_and(PyObject* self, PyObject* b)
+{
+ if (!PyNumber_Check(b)) {
+ Py_INCREF(Py_NotImplemented);
+ return Py_NotImplemented;
+ }
+
+ long valA = SBK_ENUM(self)->ob_value;
+ long valB = getNumberValue(b);
+ return PyInt_FromLong(valA & valB);
+}
+
+static PyObject* enum_or(PyObject* self, PyObject* b)
+{
+ if (!PyNumber_Check(b)) {
+ Py_INCREF(Py_NotImplemented);
+ return Py_NotImplemented;
+ }
+
+ long valA = SBK_ENUM(self)->ob_value;
+ long valB = getNumberValue(b);
+ return PyInt_FromLong(valA | valB);
+}
+
+static PyObject* enum_xor(PyObject* self, PyObject* b)
+{
+ if (!PyNumber_Check(b)) {
+ Py_INCREF(Py_NotImplemented);
+ return Py_NotImplemented;
+ }
+
+ long valA = SBK_ENUM(self)->ob_value;
+ long valB = getNumberValue(b);
+ return PyInt_FromLong(valA ^ valB);
+}
+
+static int enum_bool(PyObject* v)
+{
+ return (SBK_ENUM(v)->ob_value > 0);
+}
+
+static PyObject* enum_add(PyObject* self, PyObject* v)
+{
+ long valA = SBK_ENUM(self)->ob_value;
+ long valB = getNumberValue(v);
+ return PyInt_FromLong(valA + valB);
+}
+
+static PyObject* enum_subtract(PyObject* self, PyObject* v)
+{
+ long valA = SBK_ENUM(self)->ob_value;
+ long valB = getNumberValue(v);
+ return PyInt_FromLong(valA - valB);
+}
+
+static PyObject* enum_multiply(PyObject* self, PyObject* v)
+{
+ long valA = SBK_ENUM(self)->ob_value;
+ long valB = getNumberValue(v);
+ return PyInt_FromLong(valA * valB);
+}
+
+#ifndef IS_PY3K
+static PyObject* enum_divide(PyObject* self, PyObject* v)
+{
+ long valA = SBK_ENUM(self)->ob_value;
+ long valB = getNumberValue(v);
+ return PyLong_FromLong(valA / valB);
+}
+#endif
+
+static PyObject* enum_richcompare(PyObject* self, PyObject* other, int op)
+{
+ int result = 0;
+ if (!PyNumber_Check(other)) {
+ Py_INCREF(Py_NotImplemented);
+ return Py_NotImplemented;
+ }
+
+ long valA = SBK_ENUM(self)->ob_value;
+ long valB = getNumberValue(other);
+
+ switch (op) {
+ case Py_EQ:
+ result = (valA == valB);
+ break;
+ case Py_NE:
+ result = (valA != valB);
+ break;
+ case Py_LE:
+ result = (valA <= valB);
+ break;
+ case Py_GE:
+ result = (valA >= valB);
+ break;
+ case Py_LT:
+ result = (valA < valB);
+ break;
+ case Py_GT:
+ result = (valA > valB);
+ break;
+ default:
+ PyErr_BadArgument();
+ return NULL;
+ }
+ if (result)
+ Py_RETURN_TRUE;
+ else
+ Py_RETURN_FALSE;
+}
+
+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, 0, 0, 0},
+ {0, 0, 0, 0, 0} // Sentinel
+};
+
+static PyNumberMethods enum_as_number = {
+ /* nb_add */ enum_add,
+ /* nb_subtract */ enum_subtract,
+ /* nb_multiply */ enum_multiply,
+#ifndef IS_PY3K
+ /* nb_divide */ enum_divide,
+#endif
+ /* nb_remainder */ 0,
+ /* nb_divmod */ 0,
+ /* nb_power */ 0,
+ /* nb_negative */ 0,
+ /* nb_positive */ enum_int,
+ /* nb_absolute */ 0,
+ /* nb_bool/nb_nonzero */ enum_bool,
+ /* nb_invert */ 0,
+ /* nb_lshift */ 0,
+ /* nb_rshift */ 0,
+ /* nb_and */ enum_and,
+ /* nb_xor */ enum_xor,
+ /* nb_or */ enum_or,
+#ifndef IS_PY3K
+ /* nb_coerce */ 0,
+#endif
+ /* nb_int */ enum_int,
+#ifdef IS_PY3K
+ /* nb_reserved */ 0,
+ /* nb_float */ 0,
+#else
+ /* nb_long */ enum_int,
+ /* nb_float */ 0,
+ /* nb_oct */ 0,
+ /* nb_hex */ 0,
+#endif
+
+ /* nb_inplace_add */ 0,
+ /* nb_inplace_subtract */ 0,
+ /* nb_inplace_multiply */ 0,
+#ifndef IS_PY3K
+ /* nb_inplace_div */ 0,
+#endif
+ /* nb_inplace_remainder */ 0,
+ /* nb_inplace_power */ 0,
+ /* nb_inplace_lshift */ 0,
+ /* nb_inplace_rshift */ 0,
+ /* nb_inplace_and */ 0,
+ /* nb_inplace_xor */ 0,
+ /* nb_inplace_or */ 0,
+
+ /* nb_floor_divide */ 0,
+ /* nb_true_divide */ 0,
+ /* nb_inplace_floor_divide */ 0,
+ /* nb_inplace_true_divide */ 0,
+
+ /* nb_index */ enum_int
+};
+
+static void SbkEnumTypeDealloc(PyObject* pyObj);
+static PyObject* SbkEnumTypeTpNew(PyTypeObject* metatype, PyObject* args, PyObject* kwds);
+
+PyTypeObject SbkEnumType_Type = {
+ PyVarObject_HEAD_INIT(0, 0)
+ /*tp_name*/ "Shiboken.EnumType",
+ /*tp_basicsize*/ sizeof(SbkEnumType),
+ /*tp_itemsize*/ 0,
+ /*tp_dealloc*/ SbkEnumTypeDealloc,
+ /*tp_print*/ 0,
+ /*tp_getattr*/ 0,
+ /*tp_setattr*/ 0,
+ /*tp_compare*/ 0,
+ /*tp_repr*/ 0,
+ /*tp_as_number*/ &enum_as_number,
+ /*tp_as_sequence*/ 0,
+ /*tp_as_mapping*/ 0,
+ /*tp_hash*/ 0,
+ /*tp_call*/ 0,
+ /*tp_str*/ 0,
+ /*tp_getattro*/ 0,
+ /*tp_setattro*/ 0,
+ /*tp_as_buffer*/ 0,
+ /*tp_flags*/ Py_TPFLAGS_DEFAULT|Py_TPFLAGS_BASETYPE|Py_TPFLAGS_CHECKTYPES,
+ /*tp_doc*/ 0,
+ /*tp_traverse*/ 0,
+ /*tp_clear*/ 0,
+ /*tp_richcompare*/ 0,
+ /*tp_weaklistoffset*/ 0,
+ /*tp_iter*/ 0,
+ /*tp_iternext*/ 0,
+ /*tp_methods*/ 0,
+ /*tp_members*/ 0,
+ /*tp_getset*/ 0,
+ /*tp_base*/ &PyType_Type,
+ /*tp_dict*/ 0,
+ /*tp_descr_get*/ 0,
+ /*tp_descr_set*/ 0,
+ /*tp_dictoffset*/ 0,
+ /*tp_init*/ 0,
+ /*tp_alloc*/ PyType_GenericAlloc,
+ /*tp_new*/ SbkEnumTypeTpNew,
+ /*tp_free*/ PyObject_GC_Del,
+ /*tp_is_gc*/ 0,
+ /*tp_bases*/ 0,
+ /*tp_mro*/ 0,
+ /*tp_cache*/ 0,
+ /*tp_subclasses*/ 0,
+ /*tp_weaklist*/ 0,
+ /*tp_del*/ 0,
+ /*tp_version_tag*/ 0
+};
+
+void SbkEnumTypeDealloc(PyObject* pyObj)
+{
+ SbkEnumType* sbkType = reinterpret_cast<SbkEnumType*>(pyObj);
+
+ PyObject_GC_UnTrack(pyObj);
+ Py_TRASHCAN_SAFE_BEGIN(pyObj);
+ if (sbkType->converter) {
+ Shiboken::Conversions::deleteConverter(sbkType->converter);
+ }
+ Py_TRASHCAN_SAFE_END(pyObj);
+}
+
+PyObject* SbkEnumTypeTpNew(PyTypeObject* metatype, PyObject* args, PyObject* kwds)
+{
+ SbkEnumType* newType = reinterpret_cast<SbkEnumType*>(PyType_Type.tp_new(metatype, args, kwds));
+ if (!newType)
+ return 0;
+ return reinterpret_cast<PyObject*>(newType);
+}
+
+} // extern "C"
+
+namespace Shiboken {
+
+class DeclaredEnumTypes
+{
+public:
+ DeclaredEnumTypes();
+ ~DeclaredEnumTypes();
+ static DeclaredEnumTypes& instance();
+ void addEnumType(PyTypeObject* type);
+
+private:
+ DeclaredEnumTypes(const DeclaredEnumTypes&);
+ DeclaredEnumTypes& operator=(const DeclaredEnumTypes&);
+ std::list<PyTypeObject*> m_enumTypes;
+};
+
+namespace Enum {
+
+bool check(PyObject* pyObj)
+{
+ return Py_TYPE(pyObj->ob_type) == &SbkEnumType_Type;
+}
+
+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)) {
+ SbkEnumObject *obj = reinterpret_cast<SbkEnumObject *>(value);
+ if (obj->ob_value == itemValue) {
+ Py_INCREF(obj);
+ return value;
+ }
+ }
+ return 0;
+}
+
+static PyTypeObject* createEnum(const char* fullName, const char* cppName, const char* shortName, PyTypeObject* flagsType)
+{
+ PyTypeObject* enumType = newTypeWithName(fullName, cppName);
+ if (flagsType)
+ enumType->tp_as_number = flagsType->tp_as_number;
+ if (PyType_Ready(enumType) < 0)
+ return 0;
+ Shiboken::TypeResolver::createValueTypeResolver<int>(cppName);
+ if (shortName)
+ Shiboken::TypeResolver::createValueTypeResolver<int>(shortName);
+ return enumType;
+}
+
+PyTypeObject* createGlobalEnum(PyObject* module, const char* name, const char* fullName, const char* cppName, PyTypeObject* flagsType)
+{
+ PyTypeObject* enumType = createEnum(fullName, cppName, name, flagsType);
+ Shiboken::TypeResolver::createValueTypeResolver<int>("Qt::WindowType");
+ Shiboken::TypeResolver::createValueTypeResolver<int>("WindowType");
+ if (enumType && PyModule_AddObject(module, name, reinterpret_cast<PyObject *>(enumType)) < 0)
+ return 0;
+ if (flagsType && PyModule_AddObject(module, flagsType->tp_name, reinterpret_cast<PyObject *>(flagsType)) < 0)
+ return 0;
+ 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(scope->super.ht_type.tp_dict, name, reinterpret_cast<PyObject *>(enumType)) < 0)
+ return 0;
+ if (flagsType && PyDict_SetItemString(scope->super.ht_type.tp_dict, flagsType->tp_name, reinterpret_cast<PyObject *>(flagsType)) < 0)
+ return 0;
+ 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 0;
+ 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, SbkObjectType* scope, const char* itemName, long itemValue)
+{
+ PyObject* enumItem = createEnumItem(enumType, itemName, itemValue);
+ if (enumItem) {
+ if (PyDict_SetItemString(scope->super.ht_type.tp_dict, itemName, enumItem) < 0)
+ return false;
+ Py_DECREF(enumItem);
+ return true;
+ }
+ return false;
+}
+
+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 0;
+
+ enumObj->ob_name = itemName ? PyBytes_FromString(itemName) : 0;
+ 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);
+}
+
+PyTypeObject* newType(const char* name)
+{
+ return newTypeWithName(name, "");
+}
+
+PyTypeObject* newTypeWithName(const char* name, const char* cppName)
+{
+ PyTypeObject* type = reinterpret_cast<PyTypeObject*>(new SbkEnumType);
+ ::memset(type, 0, sizeof(SbkEnumType));
+ Py_TYPE(type) = &SbkEnumType_Type;
+ type->tp_basicsize = sizeof(SbkEnumObject);
+ type->tp_print = &SbkEnumObject_print;
+ type->tp_repr = &SbkEnumObject_repr;
+ type->tp_str = &SbkEnumObject_repr;
+ type->tp_flags = Py_TPFLAGS_DEFAULT|Py_TPFLAGS_CHECKTYPES;
+ type->tp_name = name;
+ type->tp_getset = SbkEnumGetSetList;
+ type->tp_new = SbkEnum_tp_new;
+ type->tp_as_number = &enum_as_number;
+ type->tp_richcompare = &enum_richcompare;
+ type->tp_hash = &enum_hash;
+
+ SbkEnumType* enumType = reinterpret_cast<SbkEnumType*>(type);
+ enumType->cppName = cppName;
+ enumType->converterPtr = &enumType->converter;
+ DeclaredEnumTypes::instance().addEnumType(type);
+ return type;
+}
+
+const char* getCppName(PyTypeObject* enumType)
+{
+ assert(Py_TYPE(enumType) == &SbkEnumType_Type);
+ return 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;
+ SBK_CONVERTER(enumType) = converter;
+}
+
+SbkConverter* getTypeConverter(PyTypeObject* enumType)
+{
+ //return reinterpret_cast<SbkEnumType*>(enumType)->converter;
+ return SBK_CONVERTER(enumType);
+}
+
+} // namespace Enum
+
+DeclaredEnumTypes& DeclaredEnumTypes::instance()
+{
+ static DeclaredEnumTypes me;
+ return me;
+}
+
+DeclaredEnumTypes::DeclaredEnumTypes()
+{
+}
+
+DeclaredEnumTypes::~DeclaredEnumTypes()
+{
+ std::list<PyTypeObject*>::const_iterator it = m_enumTypes.begin();
+ for (; it != m_enumTypes.end(); ++it)
+ delete *it;
+ 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
new file mode 100644
index 000000000..4b572dbcc
--- /dev/null
+++ b/sources/shiboken2/libshiboken/sbkenum.h
@@ -0,0 +1,118 @@
+/****************************************************************************
+**
+** Copyright (C) 2016 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$
+**
+****************************************************************************/
+
+#ifndef SBKENUM_H
+#define SBKENUM_H
+
+#include "sbkpython.h"
+#include "shibokenmacros.h"
+
+extern "C"
+{
+
+extern LIBSHIBOKEN_API PyTypeObject SbkEnumType_Type;
+struct SbkObjectType;
+struct SbkConverter;
+
+} // extern "C"
+
+namespace Shiboken
+{
+
+inline bool isShibokenEnum(PyObject* pyObj)
+{
+ return Py_TYPE(pyObj->ob_type) == &SbkEnumType_Type;
+}
+
+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 = 0);
+ /// 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 = 0);
+
+ /**
+ * 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, SbkObjectType* scope, const char* itemName, long itemValue);
+
+ LIBSHIBOKEN_API PyObject* newItem(PyTypeObject* enumType, long itemValue, const char* itemName = 0);
+
+ /// \deprecated Use 'newTypeWithName'
+ SBK_DEPRECATED(LIBSHIBOKEN_API PyTypeObject* newType(const char* name));
+ LIBSHIBOKEN_API PyTypeObject* newTypeWithName(const char* name, const char* cppName);
+ 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
new file mode 100644
index 000000000..084e23efa
--- /dev/null
+++ b/sources/shiboken2/libshiboken/sbkmodule.cpp
@@ -0,0 +1,124 @@
+/****************************************************************************
+**
+** Copyright (C) 2016 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$
+**
+****************************************************************************/
+
+#include "sbkmodule.h"
+#include "basewrapper.h"
+#include "bindingmanager.h"
+
+// TODO: for performance reasons this should be a sparse_hash_map,
+// because there'll be very few modules as keys. The sparse_hash_map
+// is missing from the code added in ../ext/sparsehash/google directory.
+#include "google/dense_hash_map"
+
+/// This hash maps module objects to arrays of Python types.
+typedef google::dense_hash_map<PyObject*, PyTypeObject**> ModuleTypesMap;
+
+/// This hash maps module objects to arrays of converters.
+typedef google::dense_hash_map<PyObject*, SbkConverter**> ModuleConvertersMap;
+
+/// All types produced in imported modules are mapped here.
+static ModuleTypesMap moduleTypes;
+static ModuleConvertersMap moduleConverters;
+
+namespace Shiboken
+{
+namespace Module
+{
+
+void init()
+{
+ // Initializes type registry for modules.
+ moduleTypes.set_empty_key((ModuleTypesMap::key_type)0);
+ moduleTypes.set_deleted_key((ModuleTypesMap::key_type)1);
+ moduleConverters.set_empty_key((ModuleConvertersMap::key_type)0);
+ moduleConverters.set_deleted_key((ModuleConvertersMap::key_type)1);
+}
+
+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)
+{
+ ModuleTypesMap::iterator iter = moduleTypes.find(module);
+ if (iter == moduleTypes.end())
+ moduleTypes.insert(std::make_pair(module, types));
+}
+
+PyTypeObject** getTypes(PyObject* module)
+{
+ ModuleTypesMap::iterator iter = moduleTypes.find(module);
+ return (iter == moduleTypes.end()) ? 0 : iter->second;
+}
+
+void registerTypeConverters(PyObject* module, SbkConverter** converters)
+{
+ ModuleConvertersMap::iterator iter = moduleConverters.find(module);
+ if (iter == moduleConverters.end())
+ moduleConverters.insert(std::make_pair(module, converters));
+}
+
+SbkConverter** getTypeConverters(PyObject* module)
+{
+ ModuleConvertersMap::iterator 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
new file mode 100644
index 000000000..e1ec7a860
--- /dev/null
+++ b/sources/shiboken2/libshiboken/sbkmodule.h
@@ -0,0 +1,115 @@
+/****************************************************************************
+**
+** Copyright (C) 2016 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$
+**
+****************************************************************************/
+
+#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/sbkpython.h b/sources/shiboken2/libshiboken/sbkpython.h
new file mode 100644
index 000000000..208618d50
--- /dev/null
+++ b/sources/shiboken2/libshiboken/sbkpython.h
@@ -0,0 +1,74 @@
+/****************************************************************************
+**
+** Copyright (C) 2016 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$
+**
+****************************************************************************/
+
+#ifndef SBKPYTHON_H
+#define SBKPYTHON_H
+
+#include "Python.h"
+#include "python25compat.h"
+
+#if PY_MAJOR_VERSION >= 3
+ #define IS_PY3K
+
+ #define PyInt_Type PyLong_Type
+ #define PyInt_Check PyLong_Check
+ #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
+
+#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_STR_NAME "str"
+ #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
new file mode 100644
index 000000000..598bccc46
--- /dev/null
+++ b/sources/shiboken2/libshiboken/sbkstring.cpp
@@ -0,0 +1,202 @@
+/****************************************************************************
+**
+** Copyright (C) 2016 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$
+**
+****************************************************************************/
+
+#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)
+{
+ if (check(pyobj) && (len(pyobj) == 1))
+ return true;
+
+ return false;
+}
+
+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 NULL;
+#ifdef IS_PY3K
+ if (PyUnicode_Check(str)) {
+ if (len) {
+ // We need to encode the unicode string into utf8 to know the size of returned char*.
+ Shiboken::AutoDecRef uniStr(PyUnicode_AsUTF8String(str));
+ *len = PyBytes_GET_SIZE(uniStr.object());
+ }
+ // Return unicode from str instead of uniStr, because the lifetime of the returned pointer
+ // depends on the lifetime of str.
+ return _PyUnicode_AsString(str);
+ }
+#endif
+ if (PyBytes_Check(str)) {
+ if (len)
+ *len = PyBytes_GET_SIZE(str);
+ return PyBytes_AS_STRING(str);
+ }
+ return 0;
+}
+
+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 = 0;
+#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
new file mode 100644
index 000000000..0d498da6d
--- /dev/null
+++ b/sources/shiboken2/libshiboken/sbkstring.h
@@ -0,0 +1,75 @@
+/****************************************************************************
+**
+** Copyright (C) 2016 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$
+**
+****************************************************************************/
+
+#ifndef SBKSTRING_H
+#define SBKSTRING_H
+
+#include "sbkpython.h"
+#include "shibokenmacros.h"
+
+#if PY_MAJOR_VERSION >= 3
+ #define SBK_STR_NAME "unicode"
+#else
+ #define SBK_STR_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 = 0);
+ 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
new file mode 100644
index 000000000..589c5ac26
--- /dev/null
+++ b/sources/shiboken2/libshiboken/sbkversion.h.in
@@ -0,0 +1,50 @@
+/****************************************************************************
+**
+** Copyright (C) 2016 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$
+**
+****************************************************************************/
+
+#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
+
+#endif
diff --git a/sources/shiboken2/libshiboken/shiboken.h b/sources/shiboken2/libshiboken/shiboken.h
new file mode 100644
index 000000000..2738bf51f
--- /dev/null
+++ b/sources/shiboken2/libshiboken/shiboken.h
@@ -0,0 +1,60 @@
+/****************************************************************************
+**
+** Copyright (C) 2016 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$
+**
+****************************************************************************/
+
+#ifndef SHIBOKEN_H
+#define SHIBOKEN_H
+
+#include "sbkpython.h"
+#include "autodecref.h"
+#include "basewrapper.h"
+#include "bindingmanager.h"
+#include "conversions.h"
+#include "gilstate.h"
+#include "threadstatesaver.h"
+#include "helper.h"
+#include "sbkconverter.h"
+#include "sbkenum.h"
+#include "sbkmodule.h"
+#include "sbkstring.h"
+#include "shibokenmacros.h"
+#include "typeresolver.h"
+#include "shibokenbuffer.h"
+
+#endif // SHIBOKEN_H
+
diff --git a/sources/shiboken2/libshiboken/shibokenbuffer.cpp b/sources/shiboken2/libshiboken/shibokenbuffer.cpp
new file mode 100644
index 000000000..6cc617668
--- /dev/null
+++ b/sources/shiboken2/libshiboken/shibokenbuffer.cpp
@@ -0,0 +1,96 @@
+/****************************************************************************
+**
+** Copyright (C) 2016 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$
+**
+****************************************************************************/
+
+#include "shibokenbuffer.h"
+#include <cstdlib>
+#include <cstring>
+
+bool Shiboken::Buffer::checkType(PyObject* pyObj)
+{
+ return PyObject_CheckReadBuffer(pyObj);
+}
+
+void* Shiboken::Buffer::getPointer(PyObject* pyObj, Py_ssize_t* size)
+{
+
+#ifdef IS_PY3K
+ Py_buffer view;
+ if (PyObject_GetBuffer(pyObj, &view, PyBUF_ND) == 0) {
+ if (size)
+ *size = view.len;
+ return view.buf;
+ } else {
+ return 0;
+ }
+#else
+ const void* buffer = 0;
+ Py_ssize_t bufferSize = 0;
+
+ PyObject_AsReadBuffer(pyObj, &buffer, &bufferSize);
+
+ if (size)
+ *size = bufferSize;
+ return const_cast<void*>(buffer);
+#endif
+}
+
+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;
+ return PyMemoryView_FromBuffer(&view);
+#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
new file mode 100644
index 000000000..18d86c6e1
--- /dev/null
+++ b/sources/shiboken2/libshiboken/shibokenbuffer.h
@@ -0,0 +1,85 @@
+/****************************************************************************
+**
+** Copyright (C) 2016 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$
+**
+****************************************************************************/
+
+#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 = 0);
+
+} // namespace Buffer
+} // namespace Shiboken
+
+#endif
diff --git a/sources/shiboken2/libshiboken/shibokenmacros.h b/sources/shiboken2/libshiboken/shibokenmacros.h
new file mode 100644
index 000000000..acd8f6ada
--- /dev/null
+++ b/sources/shiboken2/libshiboken/shibokenmacros.h
@@ -0,0 +1,63 @@
+/****************************************************************************
+**
+** Copyright (C) 2016 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$
+**
+****************************************************************************/
+
+#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/threadstatesaver.cpp b/sources/shiboken2/libshiboken/threadstatesaver.cpp
new file mode 100644
index 000000000..3d3ba81ab
--- /dev/null
+++ b/sources/shiboken2/libshiboken/threadstatesaver.cpp
@@ -0,0 +1,69 @@
+/****************************************************************************
+**
+** Copyright (C) 2016 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$
+**
+****************************************************************************/
+
+#include "threadstatesaver.h"
+
+namespace Shiboken
+{
+
+ThreadStateSaver::ThreadStateSaver()
+ : m_threadState(0)
+ {}
+
+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 = 0;
+ }
+}
+
+} // namespace Shiboken
+
diff --git a/sources/shiboken2/libshiboken/threadstatesaver.h b/sources/shiboken2/libshiboken/threadstatesaver.h
new file mode 100644
index 000000000..3fe595d95
--- /dev/null
+++ b/sources/shiboken2/libshiboken/threadstatesaver.h
@@ -0,0 +1,66 @@
+/****************************************************************************
+**
+** Copyright (C) 2016 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$
+**
+****************************************************************************/
+
+#ifndef THREADSTATESAVER_H
+#define THREADSTATESAVER_H
+
+#include "sbkpython.h"
+#include <shibokenmacros.h>
+
+namespace Shiboken
+{
+
+class LIBSHIBOKEN_API ThreadStateSaver
+{
+public:
+ ThreadStateSaver();
+ ~ThreadStateSaver();
+ void save();
+ void restore();
+private:
+ PyThreadState* m_threadState;
+
+ ThreadStateSaver(const ThreadStateSaver&);
+ ThreadStateSaver& operator=(const ThreadStateSaver&);
+};
+
+} // namespace Shiboken
+
+#endif // THREADSTATESAVER_H
+
diff --git a/sources/shiboken2/libshiboken/tmp-referencetopython/sbkconverter.cpp b/sources/shiboken2/libshiboken/tmp-referencetopython/sbkconverter.cpp
new file mode 100644
index 000000000..c3e25014e
--- /dev/null
+++ b/sources/shiboken2/libshiboken/tmp-referencetopython/sbkconverter.cpp
@@ -0,0 +1,213 @@
+/****************************************************************************
+**
+** Copyright (C) 2016 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$
+**
+****************************************************************************/
+
+#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((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);
+ *((void**)cppOut) = 0;
+}
+
+void pythonToCppPointer(SbkObjectType* type, PyObject* pyIn, void* cppOut)
+{
+ assert(pyIn);
+ assert(cppOut);
+ SbkObjectType* inType = (SbkObjectType*)pyIn->ob_type;
+ if (ObjectType::hasCast(inType))
+ *((void**)cppOut) = ObjectType::cast(inType, (SbkObject*)pyIn, (PyTypeObject*)type);
+ else
+ *((void**)cppOut) = Object::cppPointer((SbkObject*)pyIn, (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
new file mode 100644
index 000000000..d4bbbca1d
--- /dev/null
+++ b/sources/shiboken2/libshiboken/tmp-referencetopython/sbkconverter.h
@@ -0,0 +1,191 @@
+/****************************************************************************
+**
+** Copyright (C) 2016 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$
+**
+****************************************************************************/
+
+#ifndef SBK_CONVERTER_H
+#define SBK_CONVERTER_H
+
+#include <limits>
+#include <Python.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/typeresolver.cpp b/sources/shiboken2/libshiboken/typeresolver.cpp
new file mode 100644
index 000000000..3939fff5f
--- /dev/null
+++ b/sources/shiboken2/libshiboken/typeresolver.cpp
@@ -0,0 +1,162 @@
+/****************************************************************************
+**
+** Copyright (C) 2016 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$
+**
+****************************************************************************/
+
+#include "typeresolver.h"
+#include "google/dense_hash_map"
+#include "sbkdbg.h"
+#include <cstdlib>
+#include <string>
+#include "basewrapper_p.h"
+
+using namespace Shiboken;
+
+typedef google::dense_hash_map<std::string, TypeResolver*> TypeResolverMap;
+static TypeResolverMap typeResolverMap;
+
+struct TypeResolver::TypeResolverPrivate
+{
+ CppToPythonFunc cppToPython;
+ PythonToCppFunc pythonToCpp;
+ PyTypeObject* pyType;
+};
+
+static void deinitTypeResolver()
+{
+ for (TypeResolverMap::const_iterator it = typeResolverMap.begin(); it != typeResolverMap.end(); ++it)
+ delete it->second;
+ typeResolverMap.clear();
+}
+
+void Shiboken::initTypeResolver()
+{
+ assert(typeResolverMap.empty());
+ typeResolverMap.set_empty_key("");
+ typeResolverMap.set_deleted_key("?");
+ std::atexit(deinitTypeResolver);
+}
+
+TypeResolver::TypeResolver() : m_d(new TypeResolverPrivate)
+{
+}
+
+TypeResolver* TypeResolver::createTypeResolver(const char* typeName,
+ CppToPythonFunc cppToPy,
+ PythonToCppFunc pyToCpp,
+ PyTypeObject* pyType)
+{
+ TypeResolver*& tr = typeResolverMap[typeName];
+ if (!tr) {
+ tr = new TypeResolver;
+ tr->m_d->cppToPython = cppToPy;
+ tr->m_d->pythonToCpp = pyToCpp;
+ tr->m_d->pyType = pyType;
+
+ /*
+ * Note:
+ *
+ * Value types are also registered as object types, but the generator *always* first register the value
+ * type version in the TypeResolver and it *must* always do it! otherwise this code wont work.
+ */
+ if (pyType && PyType_IsSubtype(pyType, reinterpret_cast<PyTypeObject*>(&SbkObject_Type))) {
+ SbkObjectType* sbkType = reinterpret_cast<SbkObjectType*>(pyType);
+ // TODO-CONVERTERS: to be deprecated
+ if (!sbkType->d->type_behaviour) {
+ const size_t len = strlen(typeName);
+ sbkType->d->type_behaviour = typeName[len -1] == '*' ? BEHAVIOUR_OBJECTTYPE : BEHAVIOUR_VALUETYPE;
+ }
+ }
+ }
+ return tr;
+}
+
+TypeResolver::~TypeResolver()
+{
+ delete m_d;
+}
+
+TypeResolver* TypeResolver::get(const char* typeName)
+{
+ TypeResolverMap::const_iterator it = typeResolverMap.find(typeName);
+ if (it != typeResolverMap.end()) {
+ return it->second;
+ } else {
+ if (Py_VerboseFlag > 0)
+ SbkDbg() << "Can't find type resolver for " << typeName;
+ return 0;
+ }
+}
+
+void TypeResolver::toCpp(PyObject* pyObj, void** place)
+{
+ m_d->pythonToCpp(pyObj, place);
+}
+
+PyObject* TypeResolver::toPython(void* cppObj)
+{
+ return m_d->cppToPython(cppObj);
+}
+
+PyTypeObject* TypeResolver::pythonType()
+{
+ return m_d->pyType;
+}
+
+TypeResolver::Type TypeResolver::getType(const char* name)
+{
+ const size_t len = strlen(name);
+ bool isObjTypeName = name[len - 1] == '*';
+ if (TypeResolver::get(name)) {
+ // great, we found the type in our first attempt!
+ return isObjTypeName ? ObjectType : ValueType;
+ } else {
+ // Type not found... let's copy the string.
+ std::string typeName(name);
+ if (isObjTypeName)
+ typeName.erase(len - 1, 1);
+ else
+ typeName += '*';
+ isObjTypeName = !isObjTypeName;
+
+ if (TypeResolver::get(typeName.c_str()))
+ return isObjTypeName ? ObjectType : ValueType;
+ else
+ return UnknownType;
+ }
+}
+
diff --git a/sources/shiboken2/libshiboken/typeresolver.h b/sources/shiboken2/libshiboken/typeresolver.h
new file mode 100644
index 000000000..bc56522fe
--- /dev/null
+++ b/sources/shiboken2/libshiboken/typeresolver.h
@@ -0,0 +1,139 @@
+/****************************************************************************
+**
+** Copyright (C) 2016 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$
+**
+****************************************************************************/
+
+#ifndef TYPERESOLVER_H
+#define TYPERESOLVER_H
+
+#include "shibokenmacros.h"
+#include "conversions.h"
+
+namespace Shiboken
+{
+
+/* To C++ convertion functions. */
+template <typename T>
+inline void pythonToValueType(PyObject* pyobj, void** data)
+{
+ *reinterpret_cast<T*>(*data) = Shiboken::Converter<T>::toCpp(pyobj);
+}
+
+template <typename T>
+inline void pythonToObjectType(PyObject* pyobj, void** data)
+{
+ *reinterpret_cast<T**>(*data) = Shiboken::Converter<T*>::toCpp(pyobj);
+}
+
+template <typename T>
+inline PyObject* objectTypeToPython(void* cptr)
+{
+ return Shiboken::Converter<T*>::toPython(*reinterpret_cast<T**>(cptr));
+}
+
+template <typename T>
+inline PyObject* referenceTypeToPython(void* cptr)
+{
+ // cptr comes the same way it come when we have a value type, but
+ // we deliver a Python object of a reference
+ return Shiboken::Converter<T&>::toPython(*reinterpret_cast<T*>(cptr));
+}
+
+/**
+* \internal This function is not part of the public API.
+* Initialize the TypeResource internal cache.
+*/
+void initTypeResolver();
+
+class LIBSHIBOKEN_API TypeResolver
+{
+public:
+ enum Type
+ {
+ ObjectType,
+ ValueType,
+ UnknownType
+ };
+
+ typedef PyObject* (*CppToPythonFunc)(void*);
+ typedef void (*PythonToCppFunc)(PyObject*, void**);
+
+ ~TypeResolver();
+
+ template<typename T>
+ static TypeResolver* createValueTypeResolver(const char* typeName)
+ {
+ return createTypeResolver(typeName, &Shiboken::Converter<T>::toPython, &pythonToValueType<T>, SbkType<T>());
+ }
+
+ template<typename T>
+ static TypeResolver* createObjectTypeResolver(const char* typeName)
+ {
+ return createTypeResolver(typeName, &objectTypeToPython<T>, &pythonToObjectType<T>, SbkType<T>());
+ }
+
+ /**
+ * This kind of type resolver is used only when we have a signal with a reference in their arguments
+ * like on QSqlTableModel::primeInsert.
+ */
+ template<typename T>
+ static TypeResolver* createReferenceTypeResolver(const char* typeName)
+ {
+ return createTypeResolver(typeName, &referenceTypeToPython<T>, &pythonToValueType<T>, SbkType<T>());
+ }
+
+ static Type getType(const char* name);
+ static TypeResolver* get(const char* typeName);
+
+ PyObject* toPython(void* cppObj);
+ void toCpp(PyObject* pyObj, void** place);
+ PyTypeObject* pythonType();
+
+private:
+ struct TypeResolverPrivate;
+ TypeResolverPrivate* m_d;
+
+ TypeResolver();
+ // disable object copy
+ TypeResolver(const TypeResolver&);
+ TypeResolver& operator=(const TypeResolver&);
+
+ static TypeResolver* createTypeResolver(const char* typeName, CppToPythonFunc cppToPy, PythonToCppFunc pyToCpp, PyTypeObject* pyType);
+};
+}
+
+#endif