summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorChristian Tismer <tismer@stackless.com>2017-12-17 19:12:56 +0100
committerAlexandru Croitor <alexandru.croitor@qt.io>2018-05-30 18:13:41 +0000
commit18dc31becdd994c53a9f894087cf1ef99fbd0232 (patch)
tree3021cfa473f20102bfb63a26117776615b91b526
parent50dd4ae202d7afb3556335c056db003f5ef50532 (diff)
PEP 384-squash: Implement PEP 384
This is the condensed checkin of 18 commits which created the implementation of PEP 384. Task-number: PYSIDE-560 Change-Id: I834c659af4c2b55b268f8e8dc4cfa53f02502409 Reviewed-by: Qt CI Bot <qt_ci_bot@qt-project.org> Reviewed-by: Alexandru Croitor <alexandru.croitor@qt.io>
-rw-r--r--build_scripts/main.py8
-rw-r--r--build_scripts/options.py2
-rw-r--r--setup.py2
-rw-r--r--sources/pyside2/CMakeLists.txt41
-rw-r--r--sources/pyside2/PySide2/QtCore/glue/qbytearray_bufferprotocol.cpp2
-rw-r--r--sources/pyside2/PySide2/QtCore/glue/qbytearray_mgetitem.cpp2
-rw-r--r--sources/pyside2/PySide2/QtCore/glue/qeasingcurve_glue.cpp2
-rw-r--r--sources/pyside2/PySide2/QtCore/glue/qeasingcurve_glue.h2
-rw-r--r--sources/pyside2/PySide2/QtCore/glue/qobject_connect.cpp3
-rw-r--r--sources/pyside2/PySide2/QtCore/glue/qobject_findchild.cpp4
-rw-r--r--sources/pyside2/PySide2/QtCore/typesystem_core_common.xml59
-rw-r--r--sources/pyside2/PySide2/QtGui/typesystem_gui_common.xml2
-rw-r--r--sources/pyside2/PySide2/QtQml/pysideqmlregistertype.cpp181
-rw-r--r--sources/pyside2/PySide2/QtQml/pysideqmlregistertype.h6
-rw-r--r--sources/pyside2/PySide2/QtQuick/pysidequickregistertype.cpp8
-rw-r--r--sources/pyside2/PySide2/QtQuick/pysidequickregistertype.h2
-rw-r--r--sources/pyside2/PySide2/QtScript/typesystem_script.xml7
-rw-r--r--sources/pyside2/PySide2/QtWidgets/glue/qmenu_glue.cpp6
-rw-r--r--sources/pyside2/PySide2/QtWidgets/glue/qmenubar_glue.cpp5
-rw-r--r--sources/pyside2/PySide2/QtWidgets/typesystem_widgets_common.xml20
-rw-r--r--sources/pyside2/PySide2/typesystem_templates.xml5
-rw-r--r--sources/pyside2/libpyside/dynamicqmetaobject.cpp10
-rw-r--r--sources/pyside2/libpyside/globalreceiverv2.h1
-rw-r--r--sources/pyside2/libpyside/pyside.cpp8
-rw-r--r--sources/pyside2/libpyside/pysideclassinfo.cpp83
-rw-r--r--sources/pyside2/libpyside/pysideclassinfo.h2
-rw-r--r--sources/pyside2/libpyside/pysidemetafunction.cpp76
-rw-r--r--sources/pyside2/libpyside/pysidemetafunction.h2
-rw-r--r--sources/pyside2/libpyside/pysideproperty.cpp92
-rw-r--r--sources/pyside2/libpyside/pysideproperty.h2
-rw-r--r--sources/pyside2/libpyside/pysideqflags.cpp70
-rw-r--r--sources/pyside2/libpyside/pysideqflags.h2
-rw-r--r--sources/pyside2/libpyside/pysidesignal.cpp301
-rw-r--r--sources/pyside2/libpyside/pysidesignal.h4
-rw-r--r--sources/pyside2/libpyside/pysidesignal_p.h2
-rw-r--r--sources/pyside2/libpyside/pysideslot.cpp80
-rw-r--r--sources/pyside2/libpyside/pysideweakref.cpp74
-rw-r--r--sources/pyside2/libpyside/signalmanager.cpp.in2
-rw-r--r--sources/pyside2/libpyside/signalmanager.h1
-rw-r--r--sources/pyside2/plugins/customwidget.cpp2
-rw-r--r--sources/shiboken2/ApiExtractor/abstractmetabuilder.cpp2
-rw-r--r--sources/shiboken2/CMakeLists.txt67
-rw-r--r--sources/shiboken2/generator/shiboken2/cppgenerator.cpp447
-rw-r--r--sources/shiboken2/generator/shiboken2/shibokengenerator.cpp16
-rw-r--r--sources/shiboken2/libshiboken/CMakeLists.txt6
-rw-r--r--sources/shiboken2/libshiboken/autodecref.h2
-rw-r--r--sources/shiboken2/libshiboken/basewrapper.cpp500
-rw-r--r--sources/shiboken2/libshiboken/basewrapper.h38
-rw-r--r--sources/shiboken2/libshiboken/bindingmanager.cpp29
-rw-r--r--sources/shiboken2/libshiboken/bufferprocs27.cpp397
-rw-r--r--sources/shiboken2/libshiboken/bufferprocs27.h144
-rw-r--r--sources/shiboken2/libshiboken/pep384impl.cpp924
-rw-r--r--sources/shiboken2/libshiboken/pep384impl.h571
-rw-r--r--sources/shiboken2/libshiboken/python25compat.h2
-rw-r--r--sources/shiboken2/libshiboken/qapp_macro.cpp4
-rw-r--r--sources/shiboken2/libshiboken/qt_attribution.json12
-rw-r--r--sources/shiboken2/libshiboken/sbkarrayconverter.cpp2
-rw-r--r--sources/shiboken2/libshiboken/sbkconverter.cpp50
-rw-r--r--sources/shiboken2/libshiboken/sbkconverter.h23
-rw-r--r--sources/shiboken2/libshiboken/sbkenum.cpp375
-rw-r--r--sources/shiboken2/libshiboken/sbkenum.h11
-rw-r--r--sources/shiboken2/libshiboken/sbkpython.h11
-rw-r--r--sources/shiboken2/libshiboken/sbkstring.cpp4
-rw-r--r--sources/shiboken2/libshiboken/sbkversion.h.in3
-rw-r--r--sources/shiboken2/libshiboken/shibokenbuffer.cpp4
-rw-r--r--sources/shiboken2/libshiboken/signature.cpp181
-rw-r--r--sources/shiboken2/libshiboken/tmp-referencetopython/sbkconverter.cpp2
-rw-r--r--sources/shiboken2/libshiboken/tmp-referencetopython/sbkconverter.h2
-rw-r--r--sources/shiboken2/libshiboken/typespec.cpp776
-rw-r--r--sources/shiboken2/libshiboken/typespec.h153
-rw-r--r--sources/shiboken2/libshiboken/voidptr.cpp166
-rw-r--r--sources/shiboken2/libshiboken/voidptr.h4
-rw-r--r--sources/shiboken2/tests/minimalbinding/CMakeLists.txt3
-rw-r--r--sources/shiboken2/tests/otherbinding/CMakeLists.txt3
-rw-r--r--sources/shiboken2/tests/samplebinding/CMakeLists.txt3
-rw-r--r--sources/shiboken2/tests/samplebinding/bytearray_bufferprotocol.cpp2
-rw-r--r--sources/shiboken2/tests/samplebinding/namespace_test.py20
-rw-r--r--sources/shiboken2/tests/samplebinding/typesystem_sample.xml4
-rw-r--r--sources/shiboken2/tests/smartbinding/CMakeLists.txt3
79 files changed, 4552 insertions, 1597 deletions
diff --git a/build_scripts/main.py b/build_scripts/main.py
index 26fc191c..f2774355 100644
--- a/build_scripts/main.py
+++ b/build_scripts/main.py
@@ -985,6 +985,14 @@ class PysideBuild(_build):
cmake_cmd.append("-DPYTHON_DEBUG_LIBRARY={}".format(
self.py_library))
+ if OPTION_LIMITED_API == "yes" or not OPTION_LIMITED_API:
+ cmake_cmd.append("-DFORCE_LIMITED_API=yes")
+ elif OPTION_LIMITED_API == "no":
+ cmake_cmd.append("-DFORCE_LIMITED_API=no")
+ else:
+ raise DistutilsSetupError("option limited-api must be 'yes' or 'no' "
+ "(default yes if applicable)")
+
if OPTION_VERBOSE_BUILD:
cmake_cmd.append("-DCMAKE_VERBOSE_MAKEFILE:BOOL=ON")
diff --git a/build_scripts/options.py b/build_scripts/options.py
index 80c9041e..d7174fef 100644
--- a/build_scripts/options.py
+++ b/build_scripts/options.py
@@ -80,4 +80,4 @@ OPTION_QT_SRC = option_value("qt-src-dir")
OPTION_VERBOSE_BUILD = has_option("verbose-build")
OPTION_SANITIZE_ADDRESS = has_option("sanitize-address")
OPTION_SNAPSHOT_BUILD = has_option("snapshot-build")
-
+OPTION_LIMITED_API = option_value("limited-api")
diff --git a/setup.py b/setup.py
index ccd880b6..60b86adc 100644
--- a/setup.py
+++ b/setup.py
@@ -136,6 +136,8 @@ using `setup.py build`:
--sanitize-address will build the project with address sanitizer
enabled (Linux or macOS only).
--skip-docs skip the documentation generation.
+ --limited-api=yes|no default yes if applicable
+ Set or clear the limited API flag. Ignored for Python 2.
REQUIREMENTS:
diff --git a/sources/pyside2/CMakeLists.txt b/sources/pyside2/CMakeLists.txt
index 77382480..08647530 100644
--- a/sources/pyside2/CMakeLists.txt
+++ b/sources/pyside2/CMakeLists.txt
@@ -400,12 +400,53 @@ else()
endif()
message(STATUS "Detected OS: ${AUTO_OS}")
+# On Windows, PYTHON_LIBRARIES can be a list. Example:
+# optimized;C:/Python36/libs/python36.lib;debug;C:/Python36/libs/python36_d.lib
+# On other platforms, this result is not used at all.
+execute_process(
+ COMMAND ${PYTHON_EXECUTABLE} -c "if True:
+ for lib in '${PYTHON_LIBRARIES}'.split(';'):
+ if '/' in lib:
+ prefix, py = lib.rsplit( '/', 1)
+ if py.startswith('python3'):
+ print(prefix + '/python3.lib')
+ break
+ "
+ OUTPUT_VARIABLE PYTHON_LIMITED_LIBRARIES
+ OUTPUT_STRIP_TRAILING_WHITESPACE)
+
if (WIN32)
set(PATH_SEP "\;")
else()
set(PATH_SEP ":")
endif()
+option(FORCE_LIMITED_API "Enable the limited API." "no")
+
+set(PYTHON_LIMITED_API 0)
+if(FORCE_LIMITED_API STREQUAL "yes")
+ # GREATER_EQUAL is available only from cmake 3.7 on. We mean python 3.5 .
+ if (${PYTHON_VERSION_MAJOR} EQUAL 3 AND ${PYTHON_VERSION_MINOR} GREATER 4)
+ if (WIN32)
+ set(SHIBOKEN_PYTHON_LIBRARIES ${PYTHON_LIMITED_LIBRARIES})
+ endif()
+ add_definitions("-DPy_LIMITED_API=0x03050000")
+ set(PYTHON_LIMITED_API 1)
+ endif()
+ if (CMAKE_BUILD_TYPE STREQUAL "Release")
+ add_definitions("-DNDEBUG")
+ endif()
+endif()
+
+if (PYTHON_LIMITED_API)
+ if (WIN32 AND NOT EXISTS "${PYTHON_LIMITED_LIBRARIES}")
+ message(FATAL_ERROR "The Limited API was enabled, but ${PYTHON_LIMITED_LIBRARIES} was not found!")
+ endif()
+ message(STATUS "******************************************************")
+ message(STATUS "** Limited API enabled ${PYTHON_LIMITED_LIBRARIES}")
+ message(STATUS "******************************************************")
+endif()
+
# Define supported Qt Version
set(SUPPORTED_QT_VERSION "${QT_VERSION_MAJOR}.${QT_VERSION_MINOR}")
diff --git a/sources/pyside2/PySide2/QtCore/glue/qbytearray_bufferprotocol.cpp b/sources/pyside2/PySide2/QtCore/glue/qbytearray_bufferprotocol.cpp
index 22825a5c..ed5fef3a 100644
--- a/sources/pyside2/PySide2/QtCore/glue/qbytearray_bufferprotocol.cpp
+++ b/sources/pyside2/PySide2/QtCore/glue/qbytearray_bufferprotocol.cpp
@@ -47,7 +47,7 @@ extern "C" {
static Py_ssize_t SbkQByteArray_segcountproc(PyObject* self, Py_ssize_t* lenp)
{
if (lenp)
- *lenp = self->ob_type->tp_as_sequence->sq_length(self);
+ *lenp = Py_TYPE(self)->tp_as_sequence->sq_length(self);
return 1;
}
diff --git a/sources/pyside2/PySide2/QtCore/glue/qbytearray_mgetitem.cpp b/sources/pyside2/PySide2/QtCore/glue/qbytearray_mgetitem.cpp
index 6a997c85..f1d5a6bf 100644
--- a/sources/pyside2/PySide2/QtCore/glue/qbytearray_mgetitem.cpp
+++ b/sources/pyside2/PySide2/QtCore/glue/qbytearray_mgetitem.cpp
@@ -82,6 +82,6 @@ if (PyIndex_Check(_key)) {
} else {
PyErr_Format(PyExc_TypeError,
"list indices must be integers or slices, not %.200s",
- _key->ob_type->tp_name);
+ PepType((Py_TYPE(_key)))->tp_name);
return NULL;
}
diff --git a/sources/pyside2/PySide2/QtCore/glue/qeasingcurve_glue.cpp b/sources/pyside2/PySide2/QtCore/glue/qeasingcurve_glue.cpp
index 5d28fbf4..46a69be3 100644
--- a/sources/pyside2/PySide2/QtCore/glue/qeasingcurve_glue.cpp
+++ b/sources/pyside2/PySide2/QtCore/glue/qeasingcurve_glue.cpp
@@ -37,7 +37,7 @@
**
****************************************************************************/
-#include <Python.h>
+#include <sbkpython.h>
#include <shiboken.h>
#include <pysideweakref.h>
#include <QEasingCurve>
diff --git a/sources/pyside2/PySide2/QtCore/glue/qeasingcurve_glue.h b/sources/pyside2/PySide2/QtCore/glue/qeasingcurve_glue.h
index 7053d808..358ea9ee 100644
--- a/sources/pyside2/PySide2/QtCore/glue/qeasingcurve_glue.h
+++ b/sources/pyside2/PySide2/QtCore/glue/qeasingcurve_glue.h
@@ -40,7 +40,7 @@
#ifndef __QEASINGCURVE_GLUE__
#define __QEASINGCURVE_GLUE__
-#include <Python.h>
+#include <sbkpython.h>
#include <QEasingCurve>
class PySideEasingCurveFunctor
diff --git a/sources/pyside2/PySide2/QtCore/glue/qobject_connect.cpp b/sources/pyside2/PySide2/QtCore/glue/qobject_connect.cpp
index ed37cef3..20f3720b 100644
--- a/sources/pyside2/PySide2/QtCore/glue/qobject_connect.cpp
+++ b/sources/pyside2/PySide2/QtCore/glue/qobject_connect.cpp
@@ -43,8 +43,7 @@ static bool isDecorator(PyObject* method, PyObject* self)
if (!PyObject_HasAttr(self, methodName))
return true;
Shiboken::AutoDecRef otherMethod(PyObject_GetAttr(self, methodName));
- return reinterpret_cast<PyMethodObject*>(otherMethod.object())->im_func != \
- reinterpret_cast<PyMethodObject*>(method)->im_func;
+ return PyMethod_GET_FUNCTION(otherMethod.object()) != PyMethod_GET_FUNCTION(method);
}
static bool getReceiver(QObject *source, const char* signal, PyObject* callback, QObject** receiver, PyObject** self, QByteArray* callbackSig)
diff --git a/sources/pyside2/PySide2/QtCore/glue/qobject_findchild.cpp b/sources/pyside2/PySide2/QtCore/glue/qobject_findchild.cpp
index 464fb68b..b32d104f 100644
--- a/sources/pyside2/PySide2/QtCore/glue/qobject_findchild.cpp
+++ b/sources/pyside2/PySide2/QtCore/glue/qobject_findchild.cpp
@@ -41,7 +41,7 @@ static QObject* _findChildHelper(const QObject* parent, const QString& name, PyT
{
foreach(QObject* child, parent->children()) {
Shiboken::AutoDecRef pyChild(%CONVERTTOPYTHON[QObject*](child));
- if (PyType_IsSubtype(pyChild->ob_type, desiredType)
+ if (PyType_IsSubtype(Py_TYPE(pyChild), desiredType)
&& (name.isNull() || name == child->objectName())) {
return child;
}
@@ -71,7 +71,7 @@ static void _findChildrenHelper(const QObject* parent, const T& name, PyTypeObje
{
foreach(const QObject* child, parent->children()) {
Shiboken::AutoDecRef pyChild(%CONVERTTOPYTHON[QObject*](child));
- if (PyType_IsSubtype(pyChild->ob_type, desiredType) && _findChildrenComparator(child, name))
+ if (PyType_IsSubtype(Py_TYPE(pyChild), desiredType) && _findChildrenComparator(child, name))
PyList_Append(result, pyChild);
_findChildrenHelper(child, name, desiredType, result);
}
diff --git a/sources/pyside2/PySide2/QtCore/typesystem_core_common.xml b/sources/pyside2/PySide2/QtCore/typesystem_core_common.xml
index f0b6b964..63c3d50e 100644
--- a/sources/pyside2/PySide2/QtCore/typesystem_core_common.xml
+++ b/sources/pyside2/PySide2/QtCore/typesystem_core_common.xml
@@ -291,12 +291,18 @@
</native-to-target>
<target-to-native>
<add-conversion type="PyUnicode">
- Py_UNICODE *unicode = PyUnicode_AS_UNICODE(%in);
- #if defined(Py_UNICODE_WIDE)
+ #ifndef Py_LIMITED_API
+ Py_UNICODE* unicode = PyUnicode_AS_UNICODE(%in);
+ # if defined(Py_UNICODE_WIDE)
// cast as Py_UNICODE can be a different type
%out = QString::fromUcs4((const uint*)unicode);
- #else
+ # else
%out = QString::fromUtf16((const ushort*)unicode, PyUnicode_GET_SIZE(%in));
+ # endif
+ #else
+ wchar_t *temp = PyUnicode_AsWideCharString(%in, NULL);
+ %out = QString::fromWCharArray(temp);
+ PyMem_Free(temp);
#endif
</add-conversion>
<add-conversion type="PyString" check="py2kStrCheck(%in)">
@@ -410,7 +416,7 @@
<add-conversion type="SbkObject">
// a class supported by QVariant?
int typeCode;
- const char *typeName = QVariant_resolveMetaType(%in->ob_type, &amp;typeCode);
+ const char *typeName = QVariant_resolveMetaType(Py_TYPE(%in), &amp;typeCode);
if (!typeCode || !typeName)
return;
QVariant var(typeCode, (void*)0);
@@ -435,9 +441,9 @@
<inject-code class="native" position="beginning">
static const char *QVariant_resolveMetaType(PyTypeObject *type, int *typeId)
{
- if (PyObject_TypeCheck(type, &amp;SbkObjectType_Type)) {
- SbkObjectType *sbkType = (SbkObjectType*)type;
- const char *typeName = Shiboken::ObjectType::getOriginalName(sbkType);
+ if (PyObject_TypeCheck(type, SbkObjectType_TypeF())) {
+ SbkObjectType* sbkType = (SbkObjectType*)type;
+ const char* typeName = Shiboken::ObjectType::getOriginalName(sbkType);
if (!typeName)
return 0;
bool valueType = '*' != typeName[qstrlen(typeName) - 1];
@@ -456,15 +462,16 @@
// tp_base does not always point to the first base class, but rather to the first
// that has added any python fields or slots to its object layout.
// See https://mail.python.org/pipermail/python-list/2009-January/520733.html
- if (type->tp_bases) {
- for (int i = 0; i &lt; PyTuple_GET_SIZE(type->tp_bases); ++i) {
- const char *derivedName = QVariant_resolveMetaType((PyTypeObject*)PyTuple_GET_ITEM(type->tp_bases, i), typeId);
+ if (PepType(type)->tp_bases) {
+ for (int i = 0; i &lt; PyTuple_GET_SIZE(PepType(type)->tp_bases); ++i) {
+ const char *derivedName = QVariant_resolveMetaType((PyTypeObject*)PyTuple_GET_ITEM(
+ PepType(type)->tp_bases, i), typeId);
if (derivedName)
return derivedName;
}
}
- else if (type->tp_base) {
- return QVariant_resolveMetaType(type->tp_base, typeId);
+ else if (PepType(type)->tp_base) {
+ return QVariant_resolveMetaType(PepType(type)->tp_base, typeId);
}
}
*typeId = 0;
@@ -563,16 +570,16 @@
</add-conversion>
<add-conversion type="PyTypeObject">
const char *typeName;
- if (Shiboken::String::checkType((PyTypeObject*)%in))
+ if (Shiboken::String::checkType(reinterpret_cast&lt;PyTypeObject*&gt;(%in)))
typeName = "QString";
else if (%in == reinterpret_cast&lt;PyObject*&gt;(&amp;PyFloat_Type))
typeName = "double"; // float is a UserType in QVariant.
else if (%in == reinterpret_cast&lt;PyObject*&gt;(&amp;PyLong_Type))
typeName = "int"; // long is a UserType in QVariant.
- else if (%in->ob_type == &amp;SbkObjectType_Type)
+ else if (Py_TYPE(%in) == SbkObjectType_TypeF())
typeName = Shiboken::ObjectType::getOriginalName((SbkObjectType*)%in);
else
- typeName = (reinterpret_cast&lt;PyTypeObject*&gt;(%in))->tp_name;
+ typeName = PepType((reinterpret_cast&lt;PyTypeObject*&gt;(%in)))->tp_name;
%out = QVariant::nameToType(typeName);
</add-conversion>
<add-conversion type="PyString" check="Shiboken::String::check(%in)">
@@ -2589,7 +2596,7 @@
<add-function signature="__repr__" return-type="PyObject*">
<inject-code class="target" position="beginning">
- QByteArray b((reinterpret_cast&lt;PyObject*&gt;(%PYSELF))->ob_type->tp_name);
+ QByteArray b(PepType(Py_TYPE(%PYSELF))->tp_name);
PyObject *aux = Shiboken::String::fromStringAndSize(%CPPSELF.constData(), %CPPSELF.size());
if (PyUnicode_CheckExact(aux)) {
PyObject *tmp = PyUnicode_AsASCIIString(aux);
@@ -3088,7 +3095,7 @@
<inject-code>
Py_ssize_t size;
uchar *ptr = reinterpret_cast&lt;uchar*&gt;(Shiboken::Buffer::getPointer(%PYARG_1, &amp;size));
- %RETURN_TYPE %0 = %CPPSELF.%FUNCTION_NAME(const_cast&lt;const uchar*>(ptr), size);
+ %RETURN_TYPE %0 = %CPPSELF.%FUNCTION_NAME(const_cast&lt;const uchar*&gt;(ptr), size);
%PYARG_0 = %CONVERTTOPYTHON[%RETURN_TYPE](%0);
</inject-code>
</modify-function>
@@ -3114,8 +3121,8 @@
// %FUNCTION_NAME() - disable generation of c++ function call
(void) %2; // remove warning about unused variable
Shiboken::AutoDecRef emptyTuple(PyTuple_New(0));
- PyObject *pyTimer = Shiboken::SbkType&lt;QTimer>()->tp_new(Shiboken::SbkType&lt;QTimer>(), emptyTuple, 0);
- Shiboken::SbkType&lt;QTimer>()->tp_init(pyTimer, emptyTuple, 0);
+ PyObject *pyTimer = PepType(Shiboken::SbkType&lt;QTimer&gt;())->tp_new(Shiboken::SbkType&lt;QTimer&gt;(), emptyTuple, 0);
+ PepType(Shiboken::SbkType&lt;QTimer&gt;())->tp_init(pyTimer, emptyTuple, 0);
QTimer* timer = %CONVERTTOCPP[QTimer*](pyTimer);
Shiboken::AutoDecRef result(
@@ -3138,14 +3145,14 @@
<inject-code class="target" position="beginning">
// %FUNCTION_NAME() - disable generation of c++ function call
Shiboken::AutoDecRef emptyTuple(PyTuple_New(0));
- PyObject *pyTimer = Shiboken::SbkType&lt;QTimer>()->tp_new(Shiboken::SbkType&lt;QTimer>(), emptyTuple, 0);
- Shiboken::SbkType&lt;QTimer>()->tp_init(pyTimer, emptyTuple, 0);
+ PyObject *pyTimer = PepType(Shiboken::SbkType&lt;QTimer&gt;())->tp_new(Shiboken::SbkType&lt;QTimer&gt;(), emptyTuple, 0);
+ PepType(Shiboken::SbkType&lt;QTimer&gt;())->tp_init(pyTimer, emptyTuple, 0);
QTimer* timer = %CONVERTTOCPP[QTimer*](pyTimer);
timer->setSingleShot(true);
- if (PyObject_TypeCheck(%2, &amp;PySideSignalInstanceType)) {
+ if (PyObject_TypeCheck(%2, PySideSignalInstanceTypeF())) {
PySideSignalInstance *signalInstance = reinterpret_cast&lt;PySideSignalInstance*&gt;(%2);
- Shiboken::AutoDecRef signalSignature(Shiboken::String::fromFormat("2%s",PySide::Signal::getSignature(signalInstance)));
+ Shiboken::AutoDecRef signalSignature(Shiboken::String::fromFormat("2%s", PySide::Signal::getSignature(signalInstance)));
Shiboken::AutoDecRef result(
PyObject_CallMethod(pyTimer,
const_cast&lt;char*&gt;("connect"),
@@ -4026,7 +4033,7 @@ s1.addTransition(button.clicked, s1h)&lt;/code>
<replace-default-expression with="0" />
</modify-argument>
<inject-code>
- if (PyObject_TypeCheck(%1, &amp;PySideSignalInstanceType)) {
+ if (PyObject_TypeCheck(%1, PySideSignalInstanceTypeF())) {
PyObject *dataSource = PySide::Signal::getObject((PySideSignalInstance*)%PYARG_1);
Shiboken::AutoDecRef obType(PyObject_Type(dataSource));
QObject* sender = %CONVERTTOCPP[QObject*](dataSource);
@@ -4082,11 +4089,11 @@ s1.addTransition(button.clicked, s1h)&lt;/code>
// since it refers to a name very tied to the generator implementation.
// Check bug #362 for more information on this
// http://bugs.openbossa.org/show_bug.cgi?id=362
- if (!PyObject_TypeCheck(%1, &amp;PySideSignalInstanceType))
+ if (!PyObject_TypeCheck(%1, PySideSignalInstanceTypeF()))
goto Sbk_%TYPEFunc_%FUNCTION_NAME_TypeError;
PySideSignalInstance *signalInstance = reinterpret_cast&lt;PySideSignalInstance*&gt;(%1);
QObject* sender = %CONVERTTOCPP[QObject*](PySide::Signal::getObject(signalInstance));
- QSignalTransition*%0 = %CPPSELF->%FUNCTION_NAME(sender,PySide::Signal::getSignature(signalInstance),%2);
+ QSignalTransition *%0 = %CPPSELF->%FUNCTION_NAME(sender, PySide::Signal::getSignature(signalInstance),%2);
%PYARG_0 = %CONVERTTOPYTHON[QSignalTransition*](%0);
</inject-code>
</add-function>
diff --git a/sources/pyside2/PySide2/QtGui/typesystem_gui_common.xml b/sources/pyside2/PySide2/QtGui/typesystem_gui_common.xml
index 47bf6299..eee22b55 100644
--- a/sources/pyside2/PySide2/QtGui/typesystem_gui_common.xml
+++ b/sources/pyside2/PySide2/QtGui/typesystem_gui_common.xml
@@ -1752,7 +1752,7 @@
PyErr_Format(PyExc_TypeError, "Invalid return value in function %s, expected %s, got %s.",
"QValidator.validate",
"PySide2.QtGui.QValidator.State, (PySide2.QtGui.QValidator.State,), (PySide2.QtGui.QValidator.State, unicode) or (PySide2.QtGui.QValidator.State, unicode, int)",
- pyResult->ob_type->tp_name);
+ PepType((Py_TYPE(pyResult)))->tp_name);
return QValidator::State();
}
</template>
diff --git a/sources/pyside2/PySide2/QtQml/pysideqmlregistertype.cpp b/sources/pyside2/PySide2/QtQml/pysideqmlregistertype.cpp
index d95ae225..fa9eb634 100644
--- a/sources/pyside2/PySide2/QtQml/pysideqmlregistertype.cpp
+++ b/sources/pyside2/PySide2/QtQml/pysideqmlregistertype.cpp
@@ -120,9 +120,9 @@ int PySide::qmlRegisterType(PyObject *pyObj, const char *uri, int versionMajor,
}
PyTypeObject *pyObjType = reinterpret_cast<PyTypeObject *>(pyObj);
- if (!PySequence_Contains(pyObjType->tp_mro, reinterpret_cast<PyObject *>(qobjectType))) {
+ if (!PySequence_Contains(PepType(pyObjType)->tp_mro, reinterpret_cast<PyObject *>(qobjectType))) {
PyErr_Format(PyExc_TypeError, "A type inherited from %s expected, got %s.",
- qobjectType->tp_name, pyObjType->tp_name);
+ PepType(qobjectType)->tp_name, PepType(pyObjType)->tp_name);
return -1;
}
@@ -229,57 +229,34 @@ void propListTpFree(void* self)
PySideProperty* pySelf = reinterpret_cast<PySideProperty*>(self);
delete reinterpret_cast<QmlListProperty*>(PySide::Property::userData(pySelf));
// calls base type constructor
- Py_TYPE(pySelf)->tp_base->tp_free(self);
+ PepType(PepType(Py_TYPE(pySelf))->tp_base)->tp_free(self);
}
-PyTypeObject PropertyListType = {
- PyVarObject_HEAD_INIT(0, 0)
- "ListProperty", /*tp_name*/
- sizeof(PySideProperty), /*tp_basicsize*/
- 0, /*tp_itemsize*/
- 0, /*tp_dealloc*/
- 0, /*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*/
- Py_TPFLAGS_DEFAULT, /*tp_flags*/
- 0, /*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 */
- &PySidePropertyType, /*tp_base */
- 0, /*tp_dict */
- 0, /*tp_descr_get */
- 0, /*tp_descr_set */
- 0, /*tp_dictoffset */
- propListTpInit, /*tp_init */
- 0, /*tp_alloc */
- 0, /*tp_new */
- propListTpFree, /*tp_free */
- 0, /*tp_is_gc */
- 0, /*tp_bases */
- 0, /*tp_mro */
- 0, /*tp_cache */
- 0, /*tp_subclasses */
- 0, /*tp_weaklist */
- 0, /*tp_del */
+static PyType_Slot PropertyListType_slots[] = {
+ {Py_tp_init, (void *)propListTpInit},
+ {Py_tp_free, (void *)propListTpFree},
+ {Py_tp_dealloc, (void *)SbkDummyDealloc},
+ {0, 0}
};
+static PyType_Spec PropertyListType_spec = {
+ "PySide2.QtQml.ListProperty",
+ sizeof(PySideProperty),
+ 0,
+ Py_TPFLAGS_DEFAULT,
+ PropertyListType_slots,
+};
+
+
+PyTypeObject *PropertyListTypeF(void)
+{
+ static PyTypeObject *type = nullptr;
+ if (!type) {
+ PyObject *bases = Py_BuildValue("(O)", PySidePropertyTypeF());
+ type = (PyTypeObject *)PyType_FromSpecWithBases(&PropertyListType_spec, bases);
+ Py_XDECREF(bases);
+ }
+ return type;
+}
} // extern "C"
@@ -312,7 +289,7 @@ int propListCount(QQmlListProperty<QObject> *propList)
// Check return type
int cppResult = 0;
- PythonToCppFunc pythonToCpp;
+ PythonToCppFunc pythonToCpp = 0;
if (PyErr_Occurred())
PyErr_Print();
else if ((pythonToCpp = Shiboken::Conversions::isPythonToCppConvertible(Shiboken::Conversions::PrimitiveTypeConverter<int>(), retVal)))
@@ -387,7 +364,7 @@ QtQml_VolatileBoolObject_new(PyTypeObject *type, PyObject *args, PyObject *kwds)
return Q_NULLPTR;
QtQml_VolatileBoolObject *self
- = reinterpret_cast<QtQml_VolatileBoolObject *>(type->tp_alloc(type, 0));
+ = reinterpret_cast<QtQml_VolatileBoolObject *>(PepType(type)->tp_alloc(type, 0));
if (self != Q_NULLPTR)
self->flag = ok;
@@ -444,10 +421,10 @@ QtQml_VolatileBoolObject_repr(QtQml_VolatileBoolObject *self)
if (self->flag)
s = PyBytes_FromFormat("%s(True)",
- Py_TYPE(self)->tp_name);
+ PepType((Py_TYPE(self)))->tp_name);
else
s = PyBytes_FromFormat("%s(False)",
- Py_TYPE(self)->tp_name);
+ PepType((Py_TYPE(self)))->tp_name);
Py_XINCREF(s);
return s;
}
@@ -459,87 +436,61 @@ QtQml_VolatileBoolObject_str(QtQml_VolatileBoolObject *self)
if (self->flag)
s = PyBytes_FromFormat("%s(True) -> %p",
- Py_TYPE(self)->tp_name, &(self->flag));
+ PepType((Py_TYPE(self)))->tp_name, &(self->flag));
else
s = PyBytes_FromFormat("%s(False) -> %p",
- Py_TYPE(self)->tp_name, &(self->flag));
+ PepType((Py_TYPE(self)))->tp_name, &(self->flag));
Py_XINCREF(s);
return s;
}
-PyTypeObject QtQml_VolatileBoolType = {
- PyVarObject_HEAD_INIT(Q_NULLPTR, 0) /*ob_size*/
- "VolatileBool", /*tp_name*/
- sizeof(QtQml_VolatileBoolObject), /*tp_basicsize*/
- 0, /*tp_itemsize*/
- 0, /*tp_dealloc*/
- 0, /*tp_print*/
- 0, /*tp_getattr*/
- 0, /*tp_setattr*/
- 0, /*tp_compare*/
- reinterpret_cast<reprfunc>(QtQml_VolatileBoolObject_repr), /*tp_repr*/
- 0, /*tp_as_number*/
- 0, /*tp_as_sequence*/
- 0, /*tp_as_mapping*/
- 0, /*tp_hash */
- 0, /*tp_call*/
- reinterpret_cast<reprfunc>(QtQml_VolatileBoolObject_str), /*tp_str*/
- 0, /*tp_getattro*/
- 0, /*tp_setattro*/
- 0, /*tp_as_buffer*/
- Py_TPFLAGS_DEFAULT, /*tp_flags*/
- "VolatileBool objects contain a C++ volatile bool", /* tp_doc */
- 0, /* tp_traverse */
- 0, /* tp_clear */
- 0, /* tp_richcompare */
- 0, /* tp_weaklistoffset */
- 0, /* tp_iter */
- 0, /* tp_iternext */
- QtQml_VolatileBoolObject_methods, /* tp_methods */
- 0, /* tp_members */
- 0, /* tp_getset */
- 0, /* tp_base */
- 0, /* tp_dict */
- 0, /* tp_descr_get */
- 0, /* tp_descr_set */
- 0, /* tp_dictoffset */
- 0, /* tp_init */
- 0, /* tp_alloc */
- QtQml_VolatileBoolObject_new, /* 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 */
-#if PY_MAJOR_VERSION > 3 || PY_MAJOR_VERSION == 3 && PY_MINOR_VERSION >= 4
- 0 /* tp_finalize */
-#endif
+static PyType_Slot QtQml_VolatileBoolType_slots[] = {
+ {Py_tp_repr, (void *)reinterpret_cast<reprfunc>(QtQml_VolatileBoolObject_repr)},
+ {Py_tp_str, (void *)reinterpret_cast<reprfunc>(QtQml_VolatileBoolObject_str)},
+ {Py_tp_methods, (void *)QtQml_VolatileBoolObject_methods},
+ {Py_tp_new, (void *)QtQml_VolatileBoolObject_new},
+ {Py_tp_dealloc, (void *)SbkDummyDealloc},
+ {0, 0}
};
+static PyType_Spec QtQml_VolatileBoolType_spec = {
+ "PySide2.QtQml.VolatileBool",
+ sizeof(QtQml_VolatileBoolObject),
+ 0,
+ Py_TPFLAGS_DEFAULT,
+ QtQml_VolatileBoolType_slots,
+};
+
+
+PyTypeObject *QtQml_VolatileBoolTypeF(void)
+{
+ static PyTypeObject *type = nullptr;
+ if (!type)
+ type = (PyTypeObject *)PyType_FromSpec(&QtQml_VolatileBoolType_spec);
+ return type;
+}
void PySide::initQmlSupport(PyObject* module)
{
ElementFactory<PYSIDE_MAX_QML_TYPES - 1>::init();
// Export QmlListProperty type
- if (PyType_Ready(&PropertyListType) < 0) {
+ if (PyType_Ready(PropertyListTypeF()) < 0) {
+ PyErr_Print();
qWarning() << "Error initializing PropertyList type.";
return;
}
- Py_INCREF(reinterpret_cast<PyObject *>(&PropertyListType));
- PyModule_AddObject(module, PropertyListType.tp_name,
- reinterpret_cast<PyObject *>(&PropertyListType));
+ Py_INCREF(reinterpret_cast<PyObject *>(PropertyListTypeF()));
+ PyModule_AddObject(module, PepType_GetNameStr(PropertyListTypeF()),
+ reinterpret_cast<PyObject *>(PropertyListTypeF()));
- if (PyType_Ready(&QtQml_VolatileBoolType) < 0) {
+ if (PyType_Ready(QtQml_VolatileBoolTypeF()) < 0) {
+ PyErr_Print();
qWarning() << "Error initializing VolatileBool type.";
return;
}
- Py_INCREF(&QtQml_VolatileBoolType);
- PyModule_AddObject(module, QtQml_VolatileBoolType.tp_name,
- reinterpret_cast<PyObject *>(&QtQml_VolatileBoolType));
+ Py_INCREF(QtQml_VolatileBoolTypeF());
+ PyModule_AddObject(module, PepType_GetNameStr(QtQml_VolatileBoolTypeF()),
+ reinterpret_cast<PyObject *>(QtQml_VolatileBoolTypeF()));
}
diff --git a/sources/pyside2/PySide2/QtQml/pysideqmlregistertype.h b/sources/pyside2/PySide2/QtQml/pysideqmlregistertype.h
index a4ee7309..0ef6539a 100644
--- a/sources/pyside2/PySide2/QtQml/pysideqmlregistertype.h
+++ b/sources/pyside2/PySide2/QtQml/pysideqmlregistertype.h
@@ -40,7 +40,7 @@
#ifndef PYSIDEQMLREGISTERTYPE_H
#define PYSIDEQMLREGISTERTYPE_H
-#include <Python.h>
+#include <sbkpython.h>
struct SbkObjectType;
@@ -78,8 +78,8 @@ typedef struct {
volatile bool flag;
} QtQml_VolatileBoolObject;
-PyAPI_DATA(PyTypeObject) QtQml_VolatileBoolType;
+PyAPI_FUNC(PyTypeObject *) QtQml_VolatileBoolTypeF(void);
-#define VolatileBool_Check(op) (Py_TYPE(op) == &QtQml_VolatileBoolType)
+#define VolatileBool_Check(op) (Py_TYPE(op) == QtQml_VolatileBoolTypeF())
#endif
diff --git a/sources/pyside2/PySide2/QtQuick/pysidequickregistertype.cpp b/sources/pyside2/PySide2/QtQuick/pysidequickregistertype.cpp
index 594fa801..67ef5355 100644
--- a/sources/pyside2/PySide2/QtQuick/pysidequickregistertype.cpp
+++ b/sources/pyside2/PySide2/QtQuick/pysidequickregistertype.cpp
@@ -106,11 +106,11 @@ struct ElementFactory<0> : ElementFactoryBase<0>
typePointerName, typeListName, \
typeMetaObject, type, registered)
-bool pyTypeObjectInheritsFromClass(const PyTypeObject *pyObjType, QByteArray className)
+bool pyTypeObjectInheritsFromClass(PyTypeObject *pyObjType, QByteArray className)
{
className.append('*');
PyTypeObject *classPyType = Shiboken::Conversions::getPythonTypeObject(className.constData());
- bool isDerived = PySequence_Contains(pyObjType->tp_mro,
+ bool isDerived = PySequence_Contains(PepType(pyObjType)->tp_mro,
reinterpret_cast<PyObject *>(classPyType));
return isDerived;
}
@@ -118,7 +118,7 @@ bool pyTypeObjectInheritsFromClass(const PyTypeObject *pyObjType, QByteArray cla
template <class WrapperClass>
void registerTypeIfInheritsFromClass(
QByteArray className,
- const PyTypeObject *typeToRegister,
+ PyTypeObject *typeToRegister,
const QByteArray &typePointerName,
const QByteArray &typeListName,
QMetaObject *typeMetaObject,
@@ -190,7 +190,7 @@ bool quickRegisterType(PyObject *pyObj, const char *uri, int versionMajor, int v
PyTypeObject *pyObjType = reinterpret_cast<PyTypeObject *>(pyObj);
PyTypeObject *qQuickItemPyType =
Shiboken::Conversions::getPythonTypeObject("QQuickItem*");
- bool isQuickItem = PySequence_Contains(pyObjType->tp_mro,
+ bool isQuickItem = PySequence_Contains(PepType(pyObjType)->tp_mro,
reinterpret_cast<PyObject *>(qQuickItemPyType));
// Register only classes that inherit QQuickItem or its children.
diff --git a/sources/pyside2/PySide2/QtQuick/pysidequickregistertype.h b/sources/pyside2/PySide2/QtQuick/pysidequickregistertype.h
index 35d3edec..1955413b 100644
--- a/sources/pyside2/PySide2/QtQuick/pysidequickregistertype.h
+++ b/sources/pyside2/PySide2/QtQuick/pysidequickregistertype.h
@@ -40,7 +40,7 @@
#ifndef PYSIDE_QUICK_REGISTER_TYPE_H
#define PYSIDE_QUICK_REGISTER_TYPE_H
-#include <Python.h>
+#include <sbkpython.h>
struct SbkObjectType;
diff --git a/sources/pyside2/PySide2/QtScript/typesystem_script.xml b/sources/pyside2/PySide2/QtScript/typesystem_script.xml
index ccb2e3ab..dc089a30 100644
--- a/sources/pyside2/PySide2/QtScript/typesystem_script.xml
+++ b/sources/pyside2/PySide2/QtScript/typesystem_script.xml
@@ -84,11 +84,12 @@
<add-function signature="__repr__" return-type="PyObject*">
<inject-code class="target" position="beginning">
if (%CPPSELF.isVariant() || %CPPSELF.isString()) {
- QString format = QString().sprintf("%s(\"%s\")", ((PyObject*)%PYSELF)->ob_type->tp_name, qPrintable(%CPPSELF.toString()));
+ QString format = QString().sprintf("%s(\"%s\")",
+ PepType(Py_TYPE(%PYSELF))->tp_name,
+ qPrintable(%CPPSELF.toString()));
%PYARG_0 = Shiboken::String::fromCString(qPrintable(format));
} else {
- %PYARG_0 = Shiboken::String::fromCString(
- ((PyObject* )%PYSELF)->ob_type->tp_name);
+ %PYARG_0 = Shiboken::String::fromCString(PepType(Py_TYPE(%PYSELF))->tp_name);
}
</inject-code>
</add-function>
diff --git a/sources/pyside2/PySide2/QtWidgets/glue/qmenu_glue.cpp b/sources/pyside2/PySide2/QtWidgets/glue/qmenu_glue.cpp
index 8a4b7e62..4e9c8c3b 100644
--- a/sources/pyside2/PySide2/QtWidgets/glue/qmenu_glue.cpp
+++ b/sources/pyside2/PySide2/QtWidgets/glue/qmenu_glue.cpp
@@ -50,7 +50,11 @@ inline PyObject* addActionWithPyObject(QMenu* self, const QIcon& icon, const QSt
self->addAction(act);
PyObject* pyAct = %CONVERTTOPYTHON[QAction*](act);
- Shiboken::AutoDecRef result(PyObject_CallMethod(pyAct, "connect", "OsO", pyAct, SIGNAL(triggered()), callback));
+ Shiboken::AutoDecRef result(PyObject_CallMethod(pyAct,
+ const_cast<char *>("connect"),
+ const_cast<char *>("OsO"),
+ pyAct,
+ SIGNAL(triggered()), callback));
if (result.isNull()) {
Py_DECREF(pyAct);
return 0;
diff --git a/sources/pyside2/PySide2/QtWidgets/glue/qmenubar_glue.cpp b/sources/pyside2/PySide2/QtWidgets/glue/qmenubar_glue.cpp
index fdd62112..8cdbc2e0 100644
--- a/sources/pyside2/PySide2/QtWidgets/glue/qmenubar_glue.cpp
+++ b/sources/pyside2/PySide2/QtWidgets/glue/qmenubar_glue.cpp
@@ -45,7 +45,10 @@ addActionWithPyObject(QMenuBar* self, const QString& text, PyObject* callback)
self->addAction(act);
PyObject* pyAct = %CONVERTTOPYTHON[QAction*](act);
- PyObject* result = PyObject_CallMethod(pyAct, "connect", "OsO", pyAct,
+ PyObject* result = PyObject_CallMethod(pyAct,
+ const_cast<char *>("connect"),
+ const_cast<char *>("OsO"),
+ pyAct,
SIGNAL(triggered(bool)), callback);
if (result == 0 || result == Py_False) {
diff --git a/sources/pyside2/PySide2/QtWidgets/typesystem_widgets_common.xml b/sources/pyside2/PySide2/QtWidgets/typesystem_widgets_common.xml
index b4a6c245..11e6a9f7 100644
--- a/sources/pyside2/PySide2/QtWidgets/typesystem_widgets_common.xml
+++ b/sources/pyside2/PySide2/QtWidgets/typesystem_widgets_common.xml
@@ -269,7 +269,7 @@
<enum-type name="PanelModality" since="4.6"/>
<inject-code class="target" position="end">
PyObject *userTypeConstant = PyInt_FromLong(QGraphicsItem::UserType);
- PyDict_SetItemString(Sbk_QGraphicsItem_Type.super.ht_type.tp_dict, "UserType", userTypeConstant);
+ PyDict_SetItemString(PepType(Sbk_QGraphicsItem_TypeF())->tp_dict, "UserType", userTypeConstant);
</inject-code>
<modify-function signature="setParentItem(QGraphicsItem*)">
<modify-argument index="this">
@@ -1022,7 +1022,11 @@
%0 = new %TYPE(%1, %2);
</inject-code>
<inject-code class="target" position="end">
- Shiboken::AutoDecRef result(PyObject_CallMethod(%PYSELF, "connect", "OsO", %PYSELF, SIGNAL(activated()), %PYARG_3));
+ Shiboken::AutoDecRef result(PyObject_CallMethod(%PYSELF,
+ const_cast&lt;char *&gt;("connect"),
+ const_cast&lt;char *&gt;("OsO"),
+ %PYSELF, SIGNAL(activated()), %PYARG_3)
+ );
if (!result.isNull())
Shiboken::Object::setParent(%PYARG_2, %PYSELF);
</inject-code>
@@ -3029,7 +3033,11 @@
<inject-code>
QAction *action = %CPPSELF.addAction(%1, %2);
%PYARG_0 = %CONVERTTOPYTHON[QAction*](action);
- Shiboken::AutoDecRef result(PyObject_CallMethod(%PYARG_0, "connect", "OsO", %PYARG_0, SIGNAL(triggered()), %PYARG_3));
+ Shiboken::AutoDecRef result(PyObject_CallMethod(%PYARG_0,
+ const_cast&lt;char *&gt;("connect"),
+ const_cast&lt;char *&gt;("OsO"),
+ %PYARG_0, SIGNAL(triggered()), %PYARG_3)
+ );
</inject-code>
</modify-function>
<modify-function signature="addAction(QString,const QObject*,const char*)">
@@ -3045,7 +3053,11 @@
<inject-code>
QAction *action = %CPPSELF.addAction(%1);
%PYARG_0 = %CONVERTTOPYTHON[QAction*](action);
- Shiboken::AutoDecRef result(PyObject_CallMethod(%PYARG_0, "connect", "OsO", %PYARG_0, SIGNAL(triggered()), %PYARG_2));
+ Shiboken::AutoDecRef result(PyObject_CallMethod(%PYARG_0,
+ const_cast&lt;char *&gt;("connect"),
+ const_cast&lt;char *&gt;("OsO"),
+ %PYARG_0, SIGNAL(triggered()), %PYARG_2)
+ );
</inject-code>
</modify-function>
<modify-function signature="addAction(const QString&amp;)">
diff --git a/sources/pyside2/PySide2/typesystem_templates.xml b/sources/pyside2/PySide2/typesystem_templates.xml
index 798d02dd..103d773c 100644
--- a/sources/pyside2/PySide2/typesystem_templates.xml
+++ b/sources/pyside2/PySide2/typesystem_templates.xml
@@ -314,11 +314,12 @@
<!-- templates for __repr__ -->
<template name="repr_code">
- QString format = QString().sprintf("%s(%REPR_FORMAT)", ((PyObject*)%PYSELF)->ob_type->tp_name, %REPR_ARGS);
+ QString format = QString().sprintf("%s(%REPR_FORMAT)",
+ PepType(Py_TYPE(%PYSELF))->tp_name, %REPR_ARGS);
%PYARG_0 = Shiboken::String::fromCString(qPrintable(format));
</template>
<template name="repr_code_matrix">
- QString format= QString("%1((").arg(((PyObject*)%PYSELF)->ob_type->tp_name);
+ QString format= QString("%1((").arg(PepType(Py_TYPE(%PYSELF))->tp_name);
QList&lt; %MATRIX_TYPE &gt; cppArgs;
%MATRIX_TYPE data[%MATRIX_SIZE];
diff --git a/sources/pyside2/libpyside/dynamicqmetaobject.cpp b/sources/pyside2/libpyside/dynamicqmetaobject.cpp
index 63b52744..5b426ae8 100644
--- a/sources/pyside2/libpyside/dynamicqmetaobject.cpp
+++ b/sources/pyside2/libpyside/dynamicqmetaobject.cpp
@@ -388,7 +388,7 @@ DynamicQMetaObject::DynamicQMetaObject(PyTypeObject* type, const QMetaObject* ba
d.relatedMetaObjects = NULL;
d.static_metacall = NULL;
- m_d->m_className = QByteArray(type->tp_name).split('.').last();
+ m_d->m_className = QByteArray(PepType(type)->tp_name).split('.').last();
m_d->m_methodOffset = base->methodCount() - 1;
m_d->m_propertyOffset = base->propertyCount() - 1;
parsePythonType(type);
@@ -591,14 +591,14 @@ void DynamicQMetaObject::parsePythonType(PyTypeObject *type)
// This enforces registering of all signals and slots at type parsing time, and not later at
// signal connection time, thus making sure no method indices change which would break
// existing connections.
- const PyObject *mro = type->tp_mro;
+ const PyObject *mro = PepType(type)->tp_mro;
const Py_ssize_t basesCount = PyTuple_GET_SIZE(mro);
PyTypeObject *qObjectType = Shiboken::Conversions::getPythonTypeObject("QObject*");
QVector<PyTypeObject *> basesToCheck;
for (Py_ssize_t i = 0; i < basesCount; ++i) {
PyTypeObject *baseType = reinterpret_cast<PyTypeObject *>(PyTuple_GET_ITEM(mro, i));
if (PyType_IsSubtype(baseType, qObjectType)
- || baseType == reinterpret_cast<PyTypeObject *>(&SbkObject_Type)
+ || baseType == reinterpret_cast<PyTypeObject *>(SbkObject_TypeF())
|| baseType == reinterpret_cast<PyTypeObject *>(&PyBaseObject_Type)) {
continue;
} else {
@@ -611,7 +611,7 @@ void DynamicQMetaObject::parsePythonType(PyTypeObject *type)
// PYSIDE-315: Handle all signals first, in all involved types.
for (int baseIndex = 0, baseEnd = basesToCheck.size(); baseIndex < baseEnd; ++baseIndex) {
PyTypeObject *baseType = basesToCheck[baseIndex];
- PyObject *attrs = baseType->tp_dict;
+ PyObject *attrs = PepType(baseType)->tp_dict;
PyObject *key = 0;
PyObject *value = 0;
Py_ssize_t pos = 0;
@@ -643,7 +643,7 @@ void DynamicQMetaObject::parsePythonType(PyTypeObject *type)
// We check for this using "is_sorted()". Sorting no longer happens at all.
for (int baseIndex = 0, baseEnd = basesToCheck.size(); baseIndex < baseEnd; ++baseIndex) {
PyTypeObject *baseType = basesToCheck[baseIndex];
- PyObject *attrs = baseType->tp_dict;
+ PyObject *attrs = PepType(baseType)->tp_dict;
PyObject *key = 0;
PyObject *value = 0;
Py_ssize_t pos = 0;
diff --git a/sources/pyside2/libpyside/globalreceiverv2.h b/sources/pyside2/libpyside/globalreceiverv2.h
index af860fe1..880719d6 100644
--- a/sources/pyside2/libpyside/globalreceiverv2.h
+++ b/sources/pyside2/libpyside/globalreceiverv2.h
@@ -140,7 +140,6 @@ private:
DynamicQMetaObject m_metaObject;
DynamicSlotDataV2 *m_data;
QList<const QObject*> m_refs;
- int m_ref;
SharedMap m_sharedMap;
};
diff --git a/sources/pyside2/libpyside/pyside.cpp b/sources/pyside2/libpyside/pyside.cpp
index 6bdaf65f..15be3876 100644
--- a/sources/pyside2/libpyside/pyside.cpp
+++ b/sources/pyside2/libpyside/pyside.cpp
@@ -265,7 +265,7 @@ PyObject* getMetaDataFromQObject(QObject* cppSelf, PyObject* self, PyObject* nam
}
//mutate native signals to signal instance type
- if (attr && PyObject_TypeCheck(attr, &PySideSignalType)) {
+ if (attr && PyObject_TypeCheck(attr, PySideSignalTypeF())) {
PyObject* signal = reinterpret_cast<PyObject*>(Signal::initialize(reinterpret_cast<PySideSignal*>(attr), name, self));
PyObject_SetAttr(self, name, reinterpret_cast<PyObject*>(signal));
return signal;
@@ -309,10 +309,10 @@ PyObject* getMetaDataFromQObject(QObject* cppSelf, PyObject* self, PyObject* nam
bool inherits(PyTypeObject* objType, const char* class_name)
{
- if (strcmp(objType->tp_name, class_name) == 0)
+ if (strcmp(PepType(objType)->tp_name, class_name) == 0)
return true;
- PyTypeObject* base = (objType)->tp_base;
+ PyTypeObject* base = PepType(objType)->tp_base;
if (base == 0)
return false;
@@ -400,7 +400,7 @@ QString pyStringToQString(PyObject *str) {
#ifdef IS_PY3K
if (PyUnicode_Check(str)) {
- const char *unicodeBuffer = _PyUnicode_AsString(str);
+ const char *unicodeBuffer = _PepUnicode_AsString(str);
if (unicodeBuffer)
return QString::fromUtf8(unicodeBuffer);
}
diff --git a/sources/pyside2/libpyside/pysideclassinfo.cpp b/sources/pyside2/libpyside/pysideclassinfo.cpp
index c5e0b548..5e0ffed3 100644
--- a/sources/pyside2/libpyside/pysideclassinfo.cpp
+++ b/sources/pyside2/libpyside/pysideclassinfo.cpp
@@ -55,55 +55,30 @@ static int classInfoTpInit(PyObject*, PyObject*, PyObject*);
static void classInfoFree(void*);
static PyObject* classCall(PyObject*, PyObject*, PyObject*);
-PyTypeObject PySideClassInfoType = {
- PyVarObject_HEAD_INIT(0, 0)
- "PySide2.QtCore." CLASSINFO_CLASS_NAME, /*tp_name*/
- sizeof(PySideClassInfo), /*tp_basicsize*/
- 0, /*tp_itemsize*/
- 0, /*tp_dealloc*/
- 0, /*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 */
- classCall, /*tp_call*/
- 0, /*tp_str*/
- 0, /*tp_getattro*/
- 0, /*tp_setattro*/
- 0, /*tp_as_buffer*/
- Py_TPFLAGS_DEFAULT, /*tp_flags*/
- 0, /*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 */
- 0, /*tp_dict */
- 0, /*tp_descr_get */
- 0, /*tp_descr_set */
- 0, /*tp_dictoffset */
- classInfoTpInit, /*tp_init */
- 0, /*tp_alloc */
- classInfoTpNew, /*tp_new */
- classInfoFree, /*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 */
+static PyType_Slot PySideClassInfoType_slots[] = {
+ {Py_tp_call, (void *)classCall},
+ {Py_tp_init, (void *)classInfoTpInit},
+ {Py_tp_new, (void *)classInfoTpNew},
+ {Py_tp_free, (void *)classInfoFree},
+ {Py_tp_dealloc, (void *)SbkDummyDealloc},
+ {0, 0}
};
+static PyType_Spec PySideClassInfoType_spec = {
+ "PySide2.QtCore." CLASSINFO_CLASS_NAME,
+ sizeof(PySideClassInfo),
+ 0,
+ Py_TPFLAGS_DEFAULT,
+ PySideClassInfoType_slots,
+};
+
+
+PyTypeObject *PySideClassInfoTypeF(void)
+{
+ static PyTypeObject *type = nullptr;
+ if (!type)
+ type = (PyTypeObject *)PyType_FromSpec(&PySideClassInfoType_spec);
+ return type;
+}
PyObject *classCall(PyObject *self, PyObject *args, PyObject * /* kw */)
{
@@ -152,7 +127,7 @@ PyObject *classCall(PyObject *self, PyObject *args, PyObject * /* kw */)
static PyObject *classInfoTpNew(PyTypeObject *subtype, PyObject * /* args */, PyObject * /* kwds */)
{
- PySideClassInfo* me = reinterpret_cast<PySideClassInfo*>(subtype->tp_alloc(subtype, 0));
+ PySideClassInfo* me = reinterpret_cast<PySideClassInfo*>(PepType(subtype)->tp_alloc(subtype, 0));
me->d = new PySideClassInfoPrivate;
me->d->m_alreadyWrapped = false;
@@ -195,7 +170,7 @@ void classInfoFree(void *self)
PySideClassInfo* data = reinterpret_cast<PySideClassInfo*>(self);
delete data->d;
- pySelf->ob_type->tp_base->tp_free(self);
+ PepType(PepType(Py_TYPE(pySelf))->tp_base)->tp_free(self);
}
@@ -206,17 +181,17 @@ namespace PySide { namespace ClassInfo {
void init(PyObject* module)
{
- if (PyType_Ready(&PySideClassInfoType) < 0)
+ if (PyType_Ready(PySideClassInfoTypeF()) < 0)
return;
- Py_INCREF(&PySideClassInfoType);
- PyModule_AddObject(module, CLASSINFO_CLASS_NAME, reinterpret_cast<PyObject *>(&PySideClassInfoType));
+ Py_INCREF(PySideClassInfoTypeF());
+ PyModule_AddObject(module, CLASSINFO_CLASS_NAME, reinterpret_cast<PyObject *>(PySideClassInfoTypeF()));
}
bool checkType(PyObject* pyObj)
{
if (pyObj)
- return PyType_IsSubtype(pyObj->ob_type, &PySideClassInfoType);
+ return PyType_IsSubtype(Py_TYPE(pyObj), PySideClassInfoTypeF());
return false;
}
diff --git a/sources/pyside2/libpyside/pysideclassinfo.h b/sources/pyside2/libpyside/pysideclassinfo.h
index 91e01471..910dd9f8 100644
--- a/sources/pyside2/libpyside/pysideclassinfo.h
+++ b/sources/pyside2/libpyside/pysideclassinfo.h
@@ -47,7 +47,7 @@
extern "C"
{
- extern PYSIDE_API PyTypeObject PySideClassInfoType;
+ extern PYSIDE_API PyTypeObject *PySideClassInfoTypeF(void);
struct PySideClassInfoPrivate;
struct PYSIDE_API PySideClassInfo
diff --git a/sources/pyside2/libpyside/pysidemetafunction.cpp b/sources/pyside2/libpyside/pysidemetafunction.cpp
index a0f4b056..9839a109 100644
--- a/sources/pyside2/libpyside/pysidemetafunction.cpp
+++ b/sources/pyside2/libpyside/pysidemetafunction.cpp
@@ -58,55 +58,29 @@ struct PySideMetaFunctionPrivate
static void functionFree(void*);
static PyObject* functionCall(PyObject*, PyObject*, PyObject*);
-PyTypeObject PySideMetaFunctionType = {
- PyVarObject_HEAD_INIT(0, 0)
- /*tp_name*/ "PySide.MetaFunction",
- /*tp_basicsize*/ sizeof(PySideMetaFunction),
- /*tp_itemsize*/ 0,
- /*tp_dealloc*/ 0,
- /*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*/ functionCall,
- /*tp_str*/ 0,
- /*tp_getattro*/ 0,
- /*tp_setattro*/ 0,
- /*tp_as_buffer*/ 0,
- /*tp_flags*/ Py_TPFLAGS_DEFAULT,
- /*tp_doc*/ "MetaFunction",
- /*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*/ 0,
- /*tp_dict*/ 0,
- /*tp_descr_get*/ 0,
- /*tp_descr_set*/ 0,
- /*tp_dictoffset*/ 0,
- /*tp_init*/ 0,
- /*tp_alloc*/ 0,
- /*tp_new*/ PyType_GenericNew,
- /*tp_free*/ functionFree,
- /*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 PyType_Slot PySideMetaFunctionType_slots[] = {
+ {Py_tp_call, (void *)functionCall},
+ {Py_tp_new, (void *)PyType_GenericNew},
+ {Py_tp_free, (void *)functionFree},
+ {Py_tp_dealloc, (void *)SbkDummyDealloc},
+ {0, 0}
};
+static PyType_Spec PySideMetaFunctionType_spec = {
+ "PySide.MetaFunction",
+ sizeof(PySideMetaFunction),
+ 0,
+ Py_TPFLAGS_DEFAULT,
+ PySideMetaFunctionType_slots,
+};
+
+
+PyTypeObject *PySideMetaFunctionTypeF(void)
+{
+ static PyTypeObject *type = nullptr;
+ if (!type)
+ type = (PyTypeObject *)PyType_FromSpec(&PySideMetaFunctionType_spec);
+ return type;
+}
void functionFree(void *self)
{
@@ -130,10 +104,10 @@ namespace PySide { namespace MetaFunction {
void init(PyObject* module)
{
- if (PyType_Ready(&PySideMetaFunctionType) < 0)
+ if (PyType_Ready(PySideMetaFunctionTypeF()) < 0)
return;
- PyModule_AddObject(module, "MetaFunction", reinterpret_cast<PyObject *>(&PySideMetaFunctionType));
+ PyModule_AddObject(module, "MetaFunction", reinterpret_cast<PyObject *>(PySideMetaFunctionTypeF()));
}
PySideMetaFunction* newObject(QObject* source, int methodIndex)
@@ -144,7 +118,7 @@ PySideMetaFunction* newObject(QObject* source, int methodIndex)
QMetaMethod method = source->metaObject()->method(methodIndex);
if ((method.methodType() == QMetaMethod::Slot) ||
(method.methodType() == QMetaMethod::Method)) {
- PySideMetaFunction* function = PyObject_New(PySideMetaFunction, &PySideMetaFunctionType);
+ PySideMetaFunction* function = PyObject_New(PySideMetaFunction, PySideMetaFunctionTypeF());
function->d = new PySideMetaFunctionPrivate();
function->d->qobject = source;
function->d->methodIndex = methodIndex;
diff --git a/sources/pyside2/libpyside/pysidemetafunction.h b/sources/pyside2/libpyside/pysidemetafunction.h
index 9a4072de..020f02d4 100644
--- a/sources/pyside2/libpyside/pysidemetafunction.h
+++ b/sources/pyside2/libpyside/pysidemetafunction.h
@@ -49,7 +49,7 @@
extern "C"
{
- extern PYSIDE_API PyTypeObject PySideMetaFunctionType;
+ extern PYSIDE_API PyTypeObject *PySideMetaFunctionTypeF(void);
struct PySideMetaFunctionPrivate;
struct PYSIDE_API PySideMetaFunction
diff --git a/sources/pyside2/libpyside/pysideproperty.cpp b/sources/pyside2/libpyside/pysideproperty.cpp
index de85686c..ccec8a2c 100644
--- a/sources/pyside2/libpyside/pysideproperty.cpp
+++ b/sources/pyside2/libpyside/pysideproperty.cpp
@@ -72,55 +72,33 @@ static PyMethodDef PySidePropertyMethods[] = {
{0, 0, 0, 0}
};
-PyTypeObject PySidePropertyType = {
- PyVarObject_HEAD_INIT(0, 0)
- QPROPERTY_CLASS_NAME, /*tp_name*/
- sizeof(PySideProperty), /*tp_basicsize*/
- 0, /*tp_itemsize*/
- qpropertyDeAlloc, /*tp_dealloc*/
- 0, /*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 */
- qPropertyCall, /*tp_call*/
- 0, /*tp_str*/
- 0, /*tp_getattro*/
- 0, /*tp_setattro*/
- 0, /*tp_as_buffer*/
- Py_TPFLAGS_DEFAULT | Py_TPFLAGS_HAVE_GC, /*tp_flags*/
- 0, /*tp_doc */
- qpropertyTraverse, /*tp_traverse */
- qpropertyClear, /*tp_clear */
- 0, /*tp_richcompare */
- 0, /*tp_weaklistoffset */
- 0, /*tp_iter */
- 0, /*tp_iternext */
- PySidePropertyMethods, /*tp_methods */
- 0, /*tp_members */
- 0, /*tp_getset */
- 0, /*tp_base */
- 0, /*tp_dict */
- 0, /*tp_descr_get */
- 0, /*tp_descr_set */
- 0, /*tp_dictoffset */
- qpropertyTpInit, /*tp_init */
- 0, /*tp_alloc */
- qpropertyTpNew, /*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 */
+static PyType_Slot PySidePropertyType_slots[] = {
+ {Py_tp_dealloc, (void *)qpropertyDeAlloc},
+ {Py_tp_call, (void *)qPropertyCall},
+ {Py_tp_traverse, (void *)qpropertyTraverse},
+ {Py_tp_clear, (void *)qpropertyClear},
+ {Py_tp_methods, (void *)PySidePropertyMethods},
+ {Py_tp_init, (void *)qpropertyTpInit},
+ {Py_tp_new, (void *)qpropertyTpNew},
+ {0, 0}
};
+// Dotted modulename is crucial for PyType_FromSpec to work. Is this name right?
+static PyType_Spec PySidePropertyType_spec = {
+ "PySide2.QtCore." QPROPERTY_CLASS_NAME,
+ sizeof(PySideProperty),
+ 0,
+ Py_TPFLAGS_DEFAULT|Py_TPFLAGS_HAVE_GC|Py_TPFLAGS_BASETYPE,
+ PySidePropertyType_slots,
+};
+
+
+PyTypeObject *PySidePropertyTypeF(void)
+{
+ static PyTypeObject *type = nullptr;
+ if (!type)
+ type = (PyTypeObject *)PyType_FromSpec(&PySidePropertyType_spec);
+ return type;
+}
static void qpropertyMetaCall(PySideProperty* pp, PyObject* self, QMetaObject::Call call, void** args)
{
@@ -174,7 +152,7 @@ static void qpropertyMetaCall(PySideProperty* pp, PyObject* self, QMetaObject::C
static PyObject *qpropertyTpNew(PyTypeObject *subtype, PyObject * /* args */, PyObject * /* kwds */)
{
- PySideProperty* me = reinterpret_cast<PySideProperty*>(subtype->tp_alloc(subtype, 0));
+ PySideProperty* me = reinterpret_cast<PySideProperty*>(PepType(subtype)->tp_alloc(subtype, 0));
me->d = new PySidePropertyPrivate;
memset(me->d, 0, sizeof(PySidePropertyPrivate));
PySidePropertyPrivate* pData = me->d;
@@ -232,7 +210,7 @@ int qpropertyTpInit(PyObject* self, PyObject* args, PyObject* kwds)
void qpropertyDeAlloc(PyObject* self)
{
qpropertyClear(self);
- Py_TYPE(self)->tp_free(self);
+ PepType(Py_TYPE(self))->tp_free(self);
}
PyObject *qPropertyCall(PyObject *self, PyObject *args, PyObject * /* kw */)
@@ -329,9 +307,9 @@ namespace {
static PyObject* getFromType(PyTypeObject* type, PyObject* name)
{
PyObject* attr = 0;
- attr = PyDict_GetItem(type->tp_dict, name);
+ attr = PyDict_GetItem(PepType(type)->tp_dict, name);
if (!attr) {
- PyObject* bases = type->tp_bases;
+ PyObject* bases = PepType(type)->tp_bases;
int size = PyTuple_GET_SIZE(bases);
for(int i=0; i < size; i++) {
PyObject* base = PyTuple_GET_ITEM(bases, i);
@@ -350,17 +328,17 @@ namespace PySide { namespace Property {
void init(PyObject* module)
{
- if (PyType_Ready(&PySidePropertyType) < 0)
+ if (PyType_Ready(PySidePropertyTypeF()) < 0)
return;
- Py_INCREF(&PySidePropertyType);
- PyModule_AddObject(module, QPROPERTY_CLASS_NAME, reinterpret_cast<PyObject *>(&PySidePropertyType));
+ Py_INCREF(PySidePropertyTypeF());
+ PyModule_AddObject(module, QPROPERTY_CLASS_NAME, reinterpret_cast<PyObject *>(PySidePropertyTypeF()));
}
bool checkType(PyObject* pyObj)
{
if (pyObj) {
- return PyType_IsSubtype(pyObj->ob_type, &PySidePropertyType);
+ return PyType_IsSubtype(Py_TYPE(pyObj), PySidePropertyTypeF());
}
return false;
}
@@ -427,7 +405,7 @@ PySideProperty* getObject(PyObject* source, PyObject* name)
attr = PyDict_GetItem(dict, name);
}
- attr = getFromType(source->ob_type, name);
+ attr = getFromType(Py_TYPE(source), name);
if (attr && checkType(attr)) {
Py_INCREF(attr);
return reinterpret_cast<PySideProperty*>(attr);
diff --git a/sources/pyside2/libpyside/pysideproperty.h b/sources/pyside2/libpyside/pysideproperty.h
index d8cafc6c..d77416ab 100644
--- a/sources/pyside2/libpyside/pysideproperty.h
+++ b/sources/pyside2/libpyside/pysideproperty.h
@@ -46,7 +46,7 @@
extern "C"
{
- extern PYSIDE_API PyTypeObject PySidePropertyType;
+ extern PYSIDE_API PyTypeObject *PySidePropertyTypeF(void);
struct PySidePropertyPrivate;
struct PYSIDE_API PySideProperty
diff --git a/sources/pyside2/libpyside/pysideqflags.cpp b/sources/pyside2/libpyside/pysideqflags.cpp
index d3806985..11db70bb 100644
--- a/sources/pyside2/libpyside/pysideqflags.cpp
+++ b/sources/pyside2/libpyside/pysideqflags.cpp
@@ -44,14 +44,17 @@
extern "C" {
struct SbkConverter;
+ struct PySideQFlagsTypePrivate
+ {
+ SbkConverter** converterPtr;
+ SbkConverter* converter;
+ };
/**
* Type of all QFlags
*/
struct PySideQFlagsType
{
- PyHeapTypeObject super;
- SbkConverter** converterPtr;
- SbkConverter* converter;
+ PepTypeObject type;
};
#define PYSIDE_QFLAGS(X) reinterpret_cast<PySideQFlagsObject*>(X)
@@ -131,20 +134,61 @@ namespace PySide
{
namespace QFlags
{
- PyTypeObject* create(const char* name, PyNumberMethods* numberMethods)
+ static PyType_Slot SbkNewQFlagsType_slots[] = {
+#ifdef IS_PY3K
+ {Py_nb_bool, 0},
+#else
+ {Py_nb_nonzero, 0},
+ {Py_nb_long, 0},
+#endif
+ {Py_nb_invert, 0},
+ {Py_nb_and, 0},
+ {Py_nb_xor, 0},
+ {Py_nb_or, 0},
+ {Py_nb_int, 0},
+#ifndef IS_PY3K
+ {Py_nb_long, 0},
+#endif
+ {Py_tp_new, (void *)PySideQFlagsNew},
+ {Py_tp_richcompare, (void *)PySideQFlagsRichCompare},
+ {Py_tp_dealloc, (void *)SbkDummyDealloc},
+ {0, 0}
+ };
+ static PyType_Spec SbkNewQFlagsType_spec = {
+ "missing QFlags name", // to be inserted later
+ sizeof(PySideQFlagsObject),
+ 0,
+ Py_TPFLAGS_DEFAULT|Py_TPFLAGS_CHECKTYPES,
+ SbkNewQFlagsType_slots,
+ };
+
+ PyTypeObject *create(const char* name, PyType_Slot numberMethods[])
{
- PyTypeObject* type = reinterpret_cast<PyTypeObject*>(new PySideQFlagsType);
- ::memset(type, 0, sizeof(PySideQFlagsType));
+ char qualname[200];
+ strcpy(qualname, "PySide2.libpyside.");
+ strcat(qualname, name);
+ // Careful: PyType_FromSpec does not allocate the string.
+ PyType_Spec *newspec = new PyType_Spec;
+ newspec->name = strdup(qualname);
+ newspec->basicsize = SbkNewQFlagsType_spec.basicsize;
+ newspec->itemsize = SbkNewQFlagsType_spec.itemsize;
+ newspec->flags = SbkNewQFlagsType_spec.flags;
+ int idx = -1;
+#ifdef IS_PY3K
+# define SLOT slot
+#else
+# define SLOT slot_
+#endif
+ while (numberMethods[++idx].SLOT) {
+ assert(SbkNewQFlagsType_slots[idx].SLOT == numberMethods[idx].SLOT);
+ SbkNewQFlagsType_slots[idx].pfunc = numberMethods[idx].pfunc;
+ }
+ newspec->slots = SbkNewQFlagsType_spec.slots;
+ PyTypeObject *type = (PyTypeObject *)PyType_FromSpec(newspec);
Py_TYPE(type) = &PyType_Type;
- type->tp_basicsize = sizeof(PySideQFlagsObject);
- type->tp_flags = Py_TPFLAGS_DEFAULT | Py_TPFLAGS_CHECKTYPES;
- type->tp_name = name;
- type->tp_new = &PySideQFlagsNew;
- type->tp_as_number = numberMethods;
- type->tp_richcompare = &PySideQFlagsRichCompare;
PySideQFlagsType* flagsType = reinterpret_cast<PySideQFlagsType*>(type);
- flagsType->converterPtr = &flagsType->converter;
+ PepType_PFTP(flagsType)->converterPtr = &PepType_PFTP(flagsType)->converter;
if (PyType_Ready(type) < 0)
return 0;
diff --git a/sources/pyside2/libpyside/pysideqflags.h b/sources/pyside2/libpyside/pysideqflags.h
index e0598798..71f30808 100644
--- a/sources/pyside2/libpyside/pysideqflags.h
+++ b/sources/pyside2/libpyside/pysideqflags.h
@@ -63,7 +63,7 @@ namespace QFlags
/**
* Creates a new QFlags type.
*/
- PYSIDE_API PyTypeObject* create(const char* name, PyNumberMethods* numberMethods);
+ PYSIDE_API PyTypeObject *create(const char* name, PyType_Slot *numberMethods);
/**
* Creates a new QFlags instance of type \p type and value \p value.
*/
diff --git a/sources/pyside2/libpyside/pysidesignal.cpp b/sources/pyside2/libpyside/pysidesignal.cpp
index 76ef65b5..483e9e05 100644
--- a/sources/pyside2/libpyside/pysidesignal.cpp
+++ b/sources/pyside2/libpyside/pysidesignal.cpp
@@ -93,117 +93,73 @@ static PyObject* signalCall(PyObject*, PyObject*, PyObject*);
static PyObject* metaSignalCheck(PyObject*, PyObject*);
-static PyMappingMethods Signal_as_mapping = {
- 0,
- signalGetItem,
- 0
-};
static PyMethodDef Signal_methods[] = {
{"__instancecheck__", (PyCFunction)metaSignalCheck, METH_O, NULL},
{0, 0, 0, 0}
};
-PyTypeObject PySideSignalMetaType = {
- PyVarObject_HEAD_INIT(0, 0)
- /*tp_name*/ "PySide2.QtCore.MetaSignal",
- /*tp_basicsize*/ sizeof(PyTypeObject),
- /*tp_itemsize*/ 0,
- /*tp_dealloc*/ 0,
- /*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,
- /*tp_doc*/ 0,
- /*tp_traverse*/ 0,
- /*tp_clear*/ 0,
- /*tp_richcompare*/ 0,
- /*tp_weaklistoffset*/ 0,
- /*tp_iter*/ 0,
- /*tp_iternext*/ 0,
- /*tp_methods*/ Signal_methods,
- /*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*/ 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
+static PyType_Slot PySideSignalMetaType_slots[] = {
+ {Py_tp_methods, (void *)Signal_methods},
+ {Py_tp_base, (void *)&PyType_Type},
+ {Py_tp_free, (void *)PyObject_GC_Del},
+ {Py_tp_dealloc, (void *)SbkDummyDealloc},
+ {0, 0}
+};
+static PyType_Spec PySideSignalMetaType_spec = {
+ "PySide2.QtCore.MetaSignal",
+ 0,
+ // sizeof(PyHeapTypeObject) is filled in by PyType_FromSpecWithBases
+ // which calls PyType_Ready which calls inherit_special.
+ 0,
+ Py_TPFLAGS_DEFAULT,
+ PySideSignalMetaType_slots,
};
-PyTypeObject PySideSignalType = {
- PyVarObject_HEAD_INIT(&PySideSignalMetaType, 0)
- /*tp_name*/ "PySide2.QtCore." SIGNAL_CLASS_NAME,
- /*tp_basicsize*/ sizeof(PySideSignal),
- /*tp_itemsize*/ 0,
- /*tp_dealloc*/ 0,
- /*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*/ &Signal_as_mapping,
- /*tp_hash*/ 0,
- /*tp_call*/ signalCall,
- /*tp_str*/ signalToString,
- /*tp_getattro*/ 0,
- /*tp_setattro*/ 0,
- /*tp_as_buffer*/ 0,
- /*tp_flags*/ Py_TPFLAGS_DEFAULT,
- /*tp_doc*/ SIGNAL_CLASS_NAME,
- /*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*/ 0,
- /*tp_dict*/ 0,
- /*tp_descr_get*/ 0,
- /*tp_descr_set*/ 0,
- /*tp_dictoffset*/ 0,
- /*tp_init*/ signalTpInit,
- /*tp_alloc*/ 0,
- /*tp_new*/ PyType_GenericNew,
- /*tp_free*/ signalFree,
- /*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
+
+PyTypeObject *PySideSignalMetaTypeF(void)
+{
+ static PyTypeObject *type = nullptr;
+ if (!type) {
+ PyObject *bases = Py_BuildValue("(O)", &PyType_Type);
+ type = (PyTypeObject *)PyType_FromSpecWithBases(&PySideSignalMetaType_spec, bases);
+ Py_XDECREF(bases);
+ }
+ return type;
+}
+
+static PyType_Slot PySideSignalType_slots[] = {
+ {Py_mp_subscript, (void *)signalGetItem},
+ {Py_tp_call, (void *)signalCall},
+ {Py_tp_str, (void *)signalToString},
+ {Py_tp_init, (void *)signalTpInit},
+ {Py_tp_new, (void *)PyType_GenericNew},
+ {Py_tp_free, (void *)signalFree},
+ {Py_tp_dealloc, (void *)SbkDummyDealloc},
+ {0, 0}
+};
+static PyType_Spec PySideSignalType_spec = {
+ "PySide2.QtCore." SIGNAL_CLASS_NAME,
+ sizeof(PySideSignal),
+ 0,
+ Py_TPFLAGS_DEFAULT,
+ PySideSignalType_slots,
};
+
+PyTypeObject *PySideSignalTypeF(void)
+{
+ static PyTypeObject *type = nullptr;
+ if (!type) {
+ type = (PyTypeObject *)PyType_FromSpec(&PySideSignalType_spec);
+ PyTypeObject *hold = Py_TYPE(type);
+ Py_TYPE(type) = PySideSignalMetaTypeF();
+ Py_INCREF(Py_TYPE(type));
+ Py_DECREF(hold);
+ }
+ return type;
+}
+
static PyMethodDef SignalInstance_methods[] = {
{"connect", (PyCFunction)signalInstanceConnect, METH_VARARGS|METH_KEYWORDS, 0},
{"disconnect", signalInstanceDisconnect, METH_VARARGS, 0},
@@ -211,61 +167,31 @@ static PyMethodDef SignalInstance_methods[] = {
{0, 0, 0, 0} /* Sentinel */
};
-static PyMappingMethods SignalInstance_as_mapping = {
+static PyType_Slot PySideSignalInstanceType_slots[] = {
+ //{Py_tp_as_mapping, (void *)&SignalInstance_as_mapping},
+ {Py_mp_subscript, (void *)signalInstanceGetItem},
+ {Py_tp_call, (void *)signalInstanceCall},
+ {Py_tp_methods, (void *)SignalInstance_methods},
+ {Py_tp_new, (void *)PyType_GenericNew},
+ {Py_tp_free, (void *)signalInstanceFree},
+ {Py_tp_dealloc, (void *)SbkDummyDealloc},
+ {0, 0}
+};
+static PyType_Spec PySideSignalInstanceType_spec = {
+ "PySide2.QtCore." SIGNAL_INSTANCE_NAME,
+ sizeof(PySideSignalInstance),
0,
- signalInstanceGetItem,
- 0
+ Py_TPFLAGS_DEFAULT,
+ PySideSignalInstanceType_slots,
};
-PyTypeObject PySideSignalInstanceType = {
- PyVarObject_HEAD_INIT(0, 0)
- /*tp_name*/ "PySide2.QtCore." SIGNAL_INSTANCE_NAME,
- /*tp_basicsize*/ sizeof(PySideSignalInstance),
- /*tp_itemsize*/ 0,
- /*tp_dealloc*/ 0,
- /*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*/ &SignalInstance_as_mapping,
- /*tp_hash*/ 0,
- /*tp_call*/ signalInstanceCall,
- /*tp_str*/ 0,
- /*tp_getattro*/ 0,
- /*tp_setattro*/ 0,
- /*tp_as_buffer*/ 0,
- /*tp_flags*/ Py_TPFLAGS_DEFAULT,
- /*tp_doc*/ SIGNAL_INSTANCE_NAME,
- /*tp_traverse*/ 0,
- /*tp_clear*/ 0,
- /*tp_richcompare*/ 0,
- /*tp_weaklistoffset*/ 0,
- /*tp_iter*/ 0,
- /*tp_iternext*/ 0,
- /*tp_methods*/ SignalInstance_methods,
- /*tp_members*/ 0,
- /*tp_getset*/ 0,
- /*tp_base*/ 0,
- /*tp_dict*/ 0,
- /*tp_descr_get*/ 0,
- /*tp_descr_set*/ 0,
- /*tp_dictoffset*/ 0,
- /*tp_init*/ 0,
- /*tp_alloc*/ 0,
- /*tp_new*/ PyType_GenericNew,
- /*tp_free*/ signalInstanceFree,
- /*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
-};
+
+PyTypeObject *PySideSignalInstanceTypeF(void)
+{
+ static PyTypeObject *type =
+ (PyTypeObject *)PyType_FromSpec(&PySideSignalInstanceType_spec);
+ return type;
+}
int signalTpInit(PyObject* self, PyObject* args, PyObject* kwds)
{
@@ -327,7 +253,7 @@ void signalFree(void* self)
Py_XDECREF(data->homonymousMethod);
data->homonymousMethod = 0;
- pySelf->ob_type->tp_base->tp_free(self);
+ PepType(PepType(Py_TYPE(pySelf))->tp_base)->tp_free(self);
}
PyObject* signalGetItem(PyObject* self, PyObject* key)
@@ -372,7 +298,7 @@ void signalInstanceFree(void* self)
}
delete dataPvt;
data->d = 0;
- pySelf->ob_type->tp_base->tp_free(self);
+ PepType(PepType(Py_TYPE(pySelf))->tp_base)->tp_free(self);
}
PyObject* signalInstanceConnect(PyObject* self, PyObject* args, PyObject* kwds)
@@ -389,7 +315,7 @@ PyObject* signalInstanceConnect(PyObject* self, PyObject* args, PyObject* kwds)
Shiboken::AutoDecRef pyArgs(PyList_New(0));
bool match = false;
- if (slot->ob_type == &PySideSignalInstanceType) {
+ if (Py_TYPE(slot) == PySideSignalInstanceTypeF()) {
PySideSignalInstance* sourceWalk = source;
PySideSignalInstance* targetWalk;
@@ -427,9 +353,9 @@ PyObject* signalInstanceConnect(PyObject* self, PyObject* args, PyObject* kwds)
PyObject *function = isMethod ? PyMethod_GET_FUNCTION(slot) : slot;
PyCodeObject *objCode = reinterpret_cast<PyCodeObject *>(PyFunction_GET_CODE(function));
PyFunctionObject *function_obj = reinterpret_cast<PyFunctionObject *>(function);
- functionName = Shiboken::String::toCString(function_obj->func_name);
+ functionName = Shiboken::String::toCString(PepFunction_GetName(function_obj));
useSelf = isMethod;
- slotArgs = objCode->co_flags & CO_VARARGS ? -1 : objCode->co_argcount;
+ slotArgs = PepCode_GET_FLAGS(objCode) & CO_VARARGS ? -1 : PepCode_GET_ARGCOUNT(objCode);
if (useSelf)
slotArgs -= 1;
@@ -574,7 +500,7 @@ PyObject* signalInstanceDisconnect(PyObject* self, PyObject* args)
slot = Py_None;
bool match = false;
- if (slot->ob_type == &PySideSignalInstanceType) {
+ if (Py_TYPE(slot) == PySideSignalInstanceTypeF()) {
PySideSignalInstance* target = reinterpret_cast<PySideSignalInstance*>(slot);
if (QMetaObject::checkConnectArgs(source->d->signature, target->d->signature)) {
PyList_Append(pyArgs, source->d->source);
@@ -626,7 +552,7 @@ PyObject* signalCall(PyObject* self, PyObject* args, PyObject* kw)
return 0;
}
- descrgetfunc getDescriptor = signal->homonymousMethod->ob_type->tp_descr_get;
+ descrgetfunc getDescriptor = PepType(Py_TYPE(signal->homonymousMethod))->tp_descr_get;
// Check if there exists a method with the same name as the signal, which is also a static
// method in C++ land.
@@ -637,7 +563,7 @@ PyObject* signalCall(PyObject* self, PyObject* args, PyObject* kw)
}
// Assumes homonymousMethod is not a static method.
- ternaryfunc callFunc = signal->homonymousMethod->ob_type->tp_call;
+ ternaryfunc callFunc = PepType(Py_TYPE(signal->homonymousMethod))->tp_call;
return callFunc(homonymousMethod, args, kw);
}
@@ -649,14 +575,14 @@ PyObject* signalInstanceCall(PyObject* self, PyObject* args, PyObject* kw)
return 0;
}
- descrgetfunc getDescriptor = PySideSignal->d->homonymousMethod->ob_type->tp_descr_get;
+ descrgetfunc getDescriptor = PepType(Py_TYPE(PySideSignal->d->homonymousMethod))->tp_descr_get;
Shiboken::AutoDecRef homonymousMethod(getDescriptor(PySideSignal->d->homonymousMethod, PySideSignal->d->source, 0));
return PyCFunction_Call(homonymousMethod, args, kw);
}
static PyObject *metaSignalCheck(PyObject * /* klass */, PyObject* args)
{
- if (PyType_IsSubtype(args->ob_type, &PySideSignalInstanceType))
+ if (PyType_IsSubtype(Py_TYPE(args), PySideSignalInstanceTypeF()))
Py_RETURN_TRUE;
else
Py_RETURN_FALSE;
@@ -669,25 +595,25 @@ namespace Signal {
void init(PyObject* module)
{
- if (PyType_Ready(&PySideSignalMetaType) < 0)
+ if (PyType_Ready(PySideSignalMetaTypeF()) < 0)
return;
- if (PyType_Ready(&PySideSignalType) < 0)
+ if (PyType_Ready(PySideSignalTypeF()) < 0)
return;
- Py_INCREF(&PySideSignalType);
- PyModule_AddObject(module, SIGNAL_CLASS_NAME, reinterpret_cast<PyObject *>(&PySideSignalType));
+ Py_INCREF(PySideSignalTypeF());
+ PyModule_AddObject(module, SIGNAL_CLASS_NAME, reinterpret_cast<PyObject *>(PySideSignalTypeF()));
- if (PyType_Ready(&PySideSignalInstanceType) < 0)
+ if (PyType_Ready(PySideSignalInstanceTypeF()) < 0)
return;
- Py_INCREF(&PySideSignalInstanceType);
+ Py_INCREF(PySideSignalInstanceTypeF());
}
bool checkType(PyObject* pyObj)
{
if (pyObj)
- return PyType_IsSubtype(pyObj->ob_type, &PySideSignalType);
+ return PyType_IsSubtype(Py_TYPE(pyObj), PySideSignalTypeF());
return false;
}
@@ -699,9 +625,9 @@ void updateSourceObject(PyObject* source)
PyObject* value;
PyObject* key;
- while (PyDict_Next(objType->tp_dict, &pos, &key, &value)) {
- if (PyObject_TypeCheck(value, &PySideSignalType)) {
- Shiboken::AutoDecRef signalInstance(reinterpret_cast<PyObject *>(PyObject_New(PySideSignalInstance, &PySideSignalInstanceType)));
+ while (PyDict_Next(PepType(objType)->tp_dict, &pos, &key, &value)) {
+ if (PyObject_TypeCheck(value, PySideSignalTypeF())) {
+ Shiboken::AutoDecRef signalInstance(reinterpret_cast<PyObject *>(PyObject_New(PySideSignalInstance, PySideSignalInstanceTypeF())));
instanceInitialize(signalInstance.cast<PySideSignalInstance*>(), key, reinterpret_cast<PySideSignal*>(value), source, 0);
PyObject_SetAttr(source, key, signalInstance);
}
@@ -714,7 +640,8 @@ char* getTypeName(PyObject* type)
{
if (PyType_Check(type)) {
char* typeName = NULL;
- if (PyType_IsSubtype(reinterpret_cast<PyTypeObject*>(type), reinterpret_cast<PyTypeObject*>(&SbkObject_Type))) {
+ if (PyType_IsSubtype(reinterpret_cast<PyTypeObject*>(type),
+ reinterpret_cast<PyTypeObject*>(SbkObject_TypeF()))) {
SbkObjectType* objType = reinterpret_cast<SbkObjectType*>(type);
typeName = strdup(Shiboken::ObjectType::getOriginalName(objType));
} else {
@@ -730,7 +657,7 @@ char* getTypeName(PyObject* type)
typeName = strdup("double");
else if (objType == &PyBool_Type)
typeName = strdup("bool");
- else if (Py_TYPE(objType) == &SbkEnumType_Type)
+ else if (Py_TYPE(objType) == SbkEnumType_TypeF())
typeName = strdup(Shiboken::Enum::getCppName(objType));
else
typeName = strdup("PyObject");
@@ -763,7 +690,7 @@ char* parseSignature(PyObject* args)
return getTypeName(args);
for (Py_ssize_t i = 0, i_max = PySequence_Size(args); i < i_max; i++) {
- Shiboken::AutoDecRef arg(PySequence_ITEM(args, i));
+ Shiboken::AutoDecRef arg(PySequence_GetItem(args, i));
char* typeName = getTypeName(arg);
if (typeName) {
if (signature) {
@@ -796,7 +723,7 @@ void appendSignature(PySideSignal* self, const SignalSignature &signature)
PySideSignalInstance* initialize(PySideSignal* self, PyObject* name, PyObject* object)
{
- PySideSignalInstance* instance = PyObject_New(PySideSignalInstance, &PySideSignalInstanceType);
+ PySideSignalInstance* instance = PyObject_New(PySideSignalInstance, PySideSignalInstanceTypeF());
SbkObject* sbkObj = reinterpret_cast<SbkObject*>(object);
if (!Shiboken::Object::wasCreatedByPython(sbkObj))
Py_INCREF(object); // PYSIDE-79: this flag was crucial for a wrapper call.
@@ -827,7 +754,7 @@ void instanceInitialize(PySideSignalInstance* self, PyObject* name, PySideSignal
index++;
if (index < data->signaturesSize) {
- selfPvt->next = PyObject_New(PySideSignalInstance, &PySideSignalInstanceType);
+ selfPvt->next = PyObject_New(PySideSignalInstance, PySideSignalInstanceTypeF());
instanceInitialize(selfPvt->next, name, data, source, index);
}
}
@@ -854,7 +781,7 @@ PySideSignalInstance* newObjectFromMethod(PyObject* source, const QList<QMetaMet
PySideSignalInstance* root = 0;
PySideSignalInstance* previous = 0;
foreach (const QMetaMethod &m, methodList) {
- PySideSignalInstance* item = PyObject_New(PySideSignalInstance, &PySideSignalInstanceType);
+ PySideSignalInstance* item = PyObject_New(PySideSignalInstance, PySideSignalInstanceTypeF());
if (!root)
root = item;
@@ -881,7 +808,7 @@ PySideSignal* newObject(const char* name, ...)
{
va_list listSignatures;
char* sig = 0;
- PySideSignal* self = PyObject_New(PySideSignal, &PySideSignalType);
+ PySideSignal* self = PyObject_New(PySideSignal, PySideSignalTypeF());
self->signalName = strdup(name);
self->signaturesSize = 0;
self->signatures = 0;
@@ -928,7 +855,7 @@ static typename T::value_type join(T t, const char* sep)
static void _addSignalToWrapper(SbkObjectType* wrapperType, const char* signalName, PySideSignal* signal)
{
- PyObject* typeDict = wrapperType->super.ht_type.tp_dict;
+ PyObject* typeDict = PepType(wrapperType)->tp_dict;
PyObject* homonymousMethod;
if ((homonymousMethod = PyDict_GetItemString(typeDict, signalName))) {
Py_INCREF(homonymousMethod);
@@ -964,7 +891,7 @@ void registerSignals(SbkObjectType* pyObj, const QMetaObject* metaObject)
SignalSigMap::Iterator it = signalsFound.begin();
SignalSigMap::Iterator end = signalsFound.end();
for (; it != end; ++it) {
- PySideSignal* self = PyObject_New(PySideSignal, &PySideSignalType);
+ PySideSignal* self = PyObject_New(PySideSignal, PySideSignalTypeF());
self->signalName = strdup(it.key().constData());
self->signaturesSize = 0;
self->signatures = 0;
@@ -1047,14 +974,14 @@ QString getCallbackSignature(const char* signal, QObject* receiver, PyObject* ca
if (isMethod || isFunction) {
PyObject* function = isMethod ? PyMethod_GET_FUNCTION(callback) : callback;
PyCodeObject* objCode = reinterpret_cast<PyCodeObject*>(PyFunction_GET_CODE(function));
- functionName = Shiboken::String::toCString(reinterpret_cast<PyFunctionObject*>(function)->func_name);
+ functionName = Shiboken::String::toCString(PepFunction_GetName(function));
useSelf = isMethod;
- numArgs = objCode->co_flags & CO_VARARGS ? -1 : objCode->co_argcount;
+ numArgs = PepCode_GET_FLAGS(objCode) & CO_VARARGS ? -1 : PepCode_GET_ARGCOUNT(objCode);
} else if (PyCFunction_Check(callback)) {
const PyCFunctionObject *funcObj = reinterpret_cast<const PyCFunctionObject *>(callback);
- functionName = funcObj->m_ml->ml_name;
- useSelf = funcObj->m_self;
- const int flags = funcObj->m_ml->ml_flags;
+ functionName = PepCFunction_GET_NAMESTR(funcObj);
+ useSelf = PyCFunction_GET_SELF(funcObj);
+ const int flags = PyCFunction_GET_FLAGS(funcObj);
if (receiver) {
//Search for signature on metaobject
diff --git a/sources/pyside2/libpyside/pysidesignal.h b/sources/pyside2/libpyside/pysidesignal.h
index f5365098..abbefbb1 100644
--- a/sources/pyside2/libpyside/pysidesignal.h
+++ b/sources/pyside2/libpyside/pysidesignal.h
@@ -50,8 +50,8 @@
extern "C"
{
- extern PYSIDE_API PyTypeObject PySideSignalType;
- extern PYSIDE_API PyTypeObject PySideSignalInstanceType;
+ extern PYSIDE_API PyTypeObject *PySideSignalTypeF(void);
+ extern PYSIDE_API PyTypeObject *PySideSignalInstanceTypeF(void);
// Internal object
struct PYSIDE_API PySideSignal;
diff --git a/sources/pyside2/libpyside/pysidesignal_p.h b/sources/pyside2/libpyside/pysidesignal_p.h
index e2e28b3d..24cbde50 100644
--- a/sources/pyside2/libpyside/pysidesignal_p.h
+++ b/sources/pyside2/libpyside/pysidesignal_p.h
@@ -44,7 +44,7 @@
extern "C"
{
- extern PyTypeObject PySideSignalType;
+ extern PyTypeObject *PySideSignalTypeF(void);
struct PySideSignal {
PyObject_HEAD
diff --git a/sources/pyside2/libpyside/pysideslot.cpp b/sources/pyside2/libpyside/pysideslot.cpp
index 8f307260..db1a7d9e 100644
--- a/sources/pyside2/libpyside/pysideslot.cpp
+++ b/sources/pyside2/libpyside/pysideslot.cpp
@@ -62,55 +62,29 @@ static int slotTpInit(PyObject*, PyObject*, PyObject*);
static PyObject* slotCall(PyObject*, PyObject*, PyObject*);
// Class Definition -----------------------------------------------
-static PyTypeObject PySideSlotType = {
- PyVarObject_HEAD_INIT(0, 0)
- "PySide2.QtCore." SLOT_DEC_NAME, /*tp_name*/
- sizeof(PySideSlot), /*tp_basicsize*/
- 0, /*tp_itemsize*/
- 0, /*tp_dealloc*/
- 0, /*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 */
- slotCall, /*tp_call*/
- 0, /*tp_str*/
- 0, /*tp_getattro*/
- 0, /*tp_setattro*/
- 0, /*tp_as_buffer*/
- Py_TPFLAGS_DEFAULT, /*tp_flags*/
- SLOT_DEC_NAME, /*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 */
- 0, /*tp_dict */
- 0, /*tp_descr_get */
- 0, /*tp_descr_set */
- 0, /*tp_dictoffset */
- slotTpInit, /*tp_init */
- 0, /*tp_alloc */
- PyType_GenericNew, /*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*/
+static PyType_Slot PySideSlotType_slots[] = {
+ {Py_tp_call, (void *)slotCall},
+ {Py_tp_init, (void *)slotTpInit},
+ {Py_tp_new, (void *)PyType_GenericNew},
+ {Py_tp_dealloc, (void *)SbkDummyDealloc},
+ {0, 0}
};
+static PyType_Spec PySideSlotType_spec = {
+ "PySide2.QtCore." SLOT_DEC_NAME,
+ sizeof(PySideSlot),
+ 0,
+ Py_TPFLAGS_DEFAULT,
+ PySideSlotType_slots,
+};
+
+
+static PyTypeObject *PySideSlotTypeF(void)
+{
+ static PyTypeObject *type = nullptr;
+ if (!type)
+ type = (PyTypeObject *)PyType_FromSpec(&PySideSlotType_spec);
+ return type;
+}
int slotTpInit(PyObject *self, PyObject *args, PyObject *kw)
{
@@ -139,7 +113,7 @@ int slotTpInit(PyObject *self, PyObject *args, PyObject *kw)
data->args = typeName;
}
} else {
- PyErr_Format(PyExc_TypeError, "Unknown signal argument type: %s", argType->ob_type->tp_name);
+ PyErr_Format(PyExc_TypeError, "Unknown signal argument type: %s", PepType((Py_TYPE(argType)))->tp_name);
return -1;
}
}
@@ -166,7 +140,7 @@ PyObject *slotCall(PyObject *self, PyObject *args, PyObject * /* kw */)
PySideSlot *data = reinterpret_cast<PySideSlot*>(self);
if (!data->slotName) {
- PyObject *funcName = reinterpret_cast<PyFunctionObject*>(callback)->func_name;
+ PyObject *funcName = PepFunction_GetName(callback);
data->slotName = strdup(Shiboken::String::toCString(funcName));
}
@@ -209,11 +183,11 @@ namespace PySide { namespace Slot {
void init(PyObject* module)
{
- if (PyType_Ready(&PySideSlotType) < 0)
+ if (PyType_Ready(PySideSlotTypeF()) < 0)
return;
- Py_INCREF(&PySideSlotType);
- PyModule_AddObject(module, SLOT_DEC_NAME, reinterpret_cast<PyObject *>(&PySideSlotType));
+ Py_INCREF(PySideSlotTypeF());
+ PyModule_AddObject(module, SLOT_DEC_NAME, reinterpret_cast<PyObject *>(PySideSlotTypeF()));
}
} // namespace Slot
diff --git a/sources/pyside2/libpyside/pysideweakref.cpp b/sources/pyside2/libpyside/pysideweakref.cpp
index c31334ee..906aafd7 100644
--- a/sources/pyside2/libpyside/pysideweakref.cpp
+++ b/sources/pyside2/libpyside/pysideweakref.cpp
@@ -40,6 +40,7 @@
#include "pysideweakref.h"
#include <sbkpython.h>
+#include <shiboken.h>
typedef struct {
PyObject_HEAD
@@ -50,56 +51,27 @@ typedef struct {
static PyObject* CallableObject_call(PyObject* callable_object, PyObject* args, PyObject* kw);
-static PyTypeObject PySideCallableObjectType = {
- PyVarObject_HEAD_INIT(0, 0)
+static PyType_Slot PySideCallableObjectType_slots[] = {
+ {Py_tp_call, (void *)CallableObject_call},
+ {Py_tp_dealloc, (void *)SbkDummyDealloc},
+ {0, 0}
+};
+static PyType_Spec PySideCallableObjectType_spec = {
const_cast<char*>("PySide.Callable"),
- sizeof(PySideCallableObject), /*tp_basicsize*/
- 0, /*tp_itemsize*/
- 0, /*tp_dealloc*/
- 0, /*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 */
- CallableObject_call, /*tp_call*/
- 0, /*tp_str*/
- 0, /*tp_getattro*/
- 0, /*tp_setattro*/
- 0, /*tp_as_buffer*/
- Py_TPFLAGS_DEFAULT, /*tp_flags*/
- 0, /* 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 */
- 0, /* tp_dict */
- 0, /* tp_descr_get */
- 0, /* tp_descr_set */
- 0, /* tp_dictoffset */
- 0, /* 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 */
+ sizeof(PySideCallableObject),
+ 0,
+ Py_TPFLAGS_DEFAULT,
+ PySideCallableObjectType_slots,
};
+
+static PyTypeObject *PySideCallableObjectTypeF(void)
+{
+ static PyTypeObject *type =
+ (PyTypeObject *)PyType_FromSpec(&PySideCallableObjectType_spec);
+ return type;
+}
+
static PyObject *CallableObject_call(PyObject *callable_object, PyObject *args, PyObject * /* kw */)
{
PySideCallableObject* obj = reinterpret_cast<PySideCallableObject *>(callable_object);
@@ -116,13 +88,13 @@ PyObject* create(PyObject* obj, PySideWeakRefFunction func, void* userData)
if (obj == Py_None)
return 0;
- if (Py_TYPE(&PySideCallableObjectType) == 0)
+ if (Py_TYPE(PySideCallableObjectTypeF()) == 0)
{
- Py_TYPE(&PySideCallableObjectType) = &PyType_Type;
- PyType_Ready(&PySideCallableObjectType);
+ Py_TYPE(PySideCallableObjectTypeF()) = &PyType_Type;
+ PyType_Ready(PySideCallableObjectTypeF());
}
- PySideCallableObject* callable = PyObject_New(PySideCallableObject, &PySideCallableObjectType);
+ PySideCallableObject* callable = PyObject_New(PySideCallableObject, PySideCallableObjectTypeF());
if (!callable || PyErr_Occurred())
return 0;
diff --git a/sources/pyside2/libpyside/signalmanager.cpp.in b/sources/pyside2/libpyside/signalmanager.cpp.in
index 50f43613..c67bc636 100644
--- a/sources/pyside2/libpyside/signalmanager.cpp.in
+++ b/sources/pyside2/libpyside/signalmanager.cpp.in
@@ -590,7 +590,7 @@ int SignalManager::registerMetaMethodGetIndex(QObject* source, const char* signa
// Create a instance meta object
if (!dict || !PyDict_Contains(dict, metaObjectAttr)) {
- dmo = new DynamicQMetaObject(pySelf->ob_type, metaObject);
+ dmo = new DynamicQMetaObject(Py_TYPE(pySelf), metaObject);
#ifdef IS_PY3K
PyObject* pyDmo = PyCapsule_New(dmo, 0, destroyMetaObject);
#else
diff --git a/sources/pyside2/libpyside/signalmanager.h b/sources/pyside2/libpyside/signalmanager.h
index 4f286745..5948a7df 100644
--- a/sources/pyside2/libpyside/signalmanager.h
+++ b/sources/pyside2/libpyside/signalmanager.h
@@ -61,7 +61,6 @@ public:
PyObjectWrapper& operator=(const PyObjectWrapper &other);
private:
PyObject* m_me;
- void* m_data; //future
};
PYSIDE_API QDataStream &operator<<(QDataStream& out, const PyObjectWrapper& myObj);
diff --git a/sources/pyside2/plugins/customwidget.cpp b/sources/pyside2/plugins/customwidget.cpp
index c2ed00bd..bad05f2d 100644
--- a/sources/pyside2/plugins/customwidget.cpp
+++ b/sources/pyside2/plugins/customwidget.cpp
@@ -51,7 +51,7 @@ PyCustomWidget::PyCustomWidget(PyObject* objectType)
: m_data(new PyCustomWidgetPrivate())
{
m_data->pyObject = objectType;
- m_name = QString(reinterpret_cast<PyTypeObject*>(objectType)->tp_name);
+ m_name = QString(PepType(reinterpret_cast<PyTypeObject*>(objectType))->tp_name);
}
PyCustomWidget::~PyCustomWidget()
diff --git a/sources/shiboken2/ApiExtractor/abstractmetabuilder.cpp b/sources/shiboken2/ApiExtractor/abstractmetabuilder.cpp
index ce582d21..d76c788e 100644
--- a/sources/shiboken2/ApiExtractor/abstractmetabuilder.cpp
+++ b/sources/shiboken2/ApiExtractor/abstractmetabuilder.cpp
@@ -2647,7 +2647,7 @@ bool AbstractMetaBuilderPrivate::isQObject(const FileModelItem &dom, const QStri
classItem = ns->findClass(names.at(names.size() - 1));
}
- if (classItem == nullptr)
+ if (!classItem)
return false;
if (classItem->extendsClass(QLatin1String("QObject")))
diff --git a/sources/shiboken2/CMakeLists.txt b/sources/shiboken2/CMakeLists.txt
index 60ab7878..5720ff55 100644
--- a/sources/shiboken2/CMakeLists.txt
+++ b/sources/shiboken2/CMakeLists.txt
@@ -335,18 +335,6 @@ if (SANITIZE_ADDRESS AND NOT MSVC)
set(CMAKE_CXX_STANDARD_LIBRARIES "${CMAKE_STANDARD_LIBRARIES} -fsanitize=address")
endif()
-add_subdirectory(ApiExtractor)
-
-set(generator_plugin_DIR ${LIB_INSTALL_DIR}/generatorrunner${generator_SUFFIX})
-
-# uninstall target
-configure_file("${CMAKE_CURRENT_SOURCE_DIR}/cmake_uninstall.cmake"
- "${CMAKE_CURRENT_BINARY_DIR}/cmake_uninstall.cmake"
- IMMEDIATE @ONLY)
-add_custom_target(uninstall "${CMAKE_COMMAND}"
- -P "${CMAKE_CURRENT_BINARY_DIR}/cmake_uninstall.cmake")
-
-
# Detect if the python libs were compiled in debug mode
# On Linux distros there is no standard way to check that.
execute_process(
@@ -390,13 +378,30 @@ execute_process(
OUTPUT_VARIABLE PYTHON_WITH_COUNT_ALLOCS
OUTPUT_STRIP_TRAILING_WHITESPACE)
+# On Windows, PYTHON_LIBRARIES can be a list. Example:
+# optimized;C:/Python36/libs/python36.lib;debug;C:/Python36/libs/python36_d.lib
+# On other platforms, this result is not used at all.
+execute_process(
+ COMMAND ${PYTHON_EXECUTABLE} -c "if True:
+ for lib in '${PYTHON_LIBRARIES}'.split(';'):
+ if '/' in lib:
+ prefix, py = lib.rsplit('/', 1)
+ if py.startswith('python3'):
+ print(prefix + '/python3.lib')
+ break
+ "
+ OUTPUT_VARIABLE PYTHON_LIMITED_LIBRARIES
+ OUTPUT_STRIP_TRAILING_WHITESPACE)
+
set(SHIBOKEN_BUILD_TYPE "Release")
-# We do not want to link against the python shared / static library on Linux And macOS.
+# We do not want to link against the python shared / static library on Linux and macOS.
# The dynamic linker will pick up the python symbols at runtime automatically.
# On Windows we do need to link against the python.lib import library.
set(SBK_PYTHON_LIBRARIES "")
+option(FORCE_LIMITED_API "Enable the limited API." "no")
+set(PYTHON_LIMITED_API 0)
if(CMAKE_BUILD_TYPE STREQUAL "Debug")
if(NOT PYTHON_DEBUG_LIBRARIES)
message(WARNING "Python debug shared library not found; assuming python was built with shared library support disabled.")
@@ -420,11 +425,32 @@ if(CMAKE_BUILD_TYPE STREQUAL "Debug")
set(SBK_PYTHON_LIBRARIES ${PYTHON_DEBUG_LIBRARIES})
endif()
set(SHIBOKEN_BUILD_TYPE "Debug")
-else()
+endif()
+if(FORCE_LIMITED_API STREQUAL "yes")
+ if (${PYTHON_VERSION_MAJOR} EQUAL 3 AND ${PYTHON_VERSION_MINOR} GREATER 4)
+ # GREATER_EQUAL is available only from cmake 3.7 on. We mean python 3.5 .
+ add_definitions("-DPy_LIMITED_API=0x03050000")
+ set(PYTHON_LIMITED_API 1)
+ endif()
if(WIN32)
set(SBK_PYTHON_LIBRARIES ${PYTHON_LIBRARIES})
+ if (${PYTHON_VERSION_MAJOR} EQUAL 3 AND ${PYTHON_VERSION_MINOR} GREATER 4)
+ # PYSIDE-560: XXX maybe add an option to setup.py as override
+ set(SBK_PYTHON_LIBRARIES ${PYTHON_LIMITED_LIBRARIES})
+ endif()
+ endif()
+ if (CMAKE_BUILD_TYPE STREQUAL "Release")
+ add_definitions("-DNDEBUG")
endif()
- add_definitions("-DNDEBUG")
+endif()
+
+if (PYTHON_LIMITED_API)
+ if (WIN32 AND NOT EXISTS "${PYTHON_LIMITED_LIBRARIES}")
+ message(FATAL_ERROR "The Limited API was enabled, but ${PYTHON_LIMITED_LIBRARIES} was not found!")
+ endif()
+ message(STATUS "******************************************************")
+ message(STATUS "** Limited API enabled ${PYTHON_LIMITED_LIBRARIES}")
+ message(STATUS "******************************************************")
endif()
if(APPLE)
@@ -437,6 +463,17 @@ else()
set(SBK_PYTHON_INCLUDE_DIR ${PYTHON_INCLUDE_DIRS})
endif()
+add_subdirectory(ApiExtractor)
+
+set(generator_plugin_DIR ${LIB_INSTALL_DIR}/generatorrunner${generator_SUFFIX})
+
+# uninstall target
+configure_file("${CMAKE_CURRENT_SOURCE_DIR}/cmake_uninstall.cmake"
+ "${CMAKE_CURRENT_BINARY_DIR}/cmake_uninstall.cmake"
+ IMMEDIATE @ONLY)
+add_custom_target(uninstall "${CMAKE_COMMAND}"
+ -P "${CMAKE_CURRENT_BINARY_DIR}/cmake_uninstall.cmake")
+
add_subdirectory(libshiboken)
add_subdirectory(doc)
diff --git a/sources/shiboken2/generator/shiboken2/cppgenerator.cpp b/sources/shiboken2/generator/shiboken2/cppgenerator.cpp
index d7c04d3c..bd654f17 100644
--- a/sources/shiboken2/generator/shiboken2/cppgenerator.cpp
+++ b/sources/shiboken2/generator/shiboken2/cppgenerator.cpp
@@ -214,6 +214,8 @@ static QString chopType(QString s)
{
if (s.endsWith(QLatin1String("_Type")))
s.chop(5);
+ else if (s.endsWith(QLatin1String("_TypeF()")))
+ s.chop(8);
return s;
}
@@ -665,7 +667,7 @@ QString CppGenerator::getVirtualFunctionReturnTypeName(const AbstractMetaFunctio
if (func->type()->isPrimitive())
return QLatin1Char('"') + func->type()->name() + QLatin1Char('"');
- return QString::fromLatin1("Shiboken::SbkType< %1 >()->tp_name").arg(func->type()->typeEntry()->qualifiedCppName());
+ return QString::fromLatin1("PepType(Shiboken::SbkType< %1 >())->tp_name").arg(func->type()->typeEntry()->qualifiedCppName());
}
void CppGenerator::writeVirtualMethodNative(QTextStream&s, const AbstractMetaFunction* func)
@@ -892,7 +894,7 @@ void CppGenerator::writeVirtualMethodNative(QTextStream&s, const AbstractMetaFun
s << INDENT << "Shiboken::warning(PyExc_RuntimeWarning, 2, "\
"\"Invalid return value in function %s, expected %s, got %s.\", \"";
s << func->ownerClass()->name() << '.' << funcName << "\", " << getVirtualFunctionReturnTypeName(func);
- s << ", " PYTHON_RETURN_VAR "->ob_type->tp_name);" << endl;
+ s << ", PepType(Py_TYPE(" PYTHON_RETURN_VAR "))->tp_name);" << endl;
s << INDENT << "return " << defaultReturnExpr << ';' << endl;
}
s << INDENT << '}' << endl;
@@ -912,7 +914,7 @@ void CppGenerator::writeVirtualMethodNative(QTextStream&s, const AbstractMetaFun
s << INDENT << "Shiboken::warning(PyExc_RuntimeWarning, 2, "\
"\"Invalid return value in function %s, expected %s, got %s.\", \"";
s << func->ownerClass()->name() << '.' << funcName << "\", " << getVirtualFunctionReturnTypeName(func);
- s << ", " PYTHON_RETURN_VAR "->ob_type->tp_name);" << endl;
+ s << ", PepType(Py_TYPE(" PYTHON_RETURN_VAR "))->tp_name);" << endl;
s << INDENT << "return " << defaultReturnExpr << ';' << endl;
}
s << INDENT << '}' << endl;
@@ -1144,11 +1146,11 @@ void CppGenerator::writeConverterFunctions(QTextStream &s, const AbstractMetaCla
QString targetTypeName = metaClass->name() + QLatin1String("_PTR");
QString code;
QTextStream c(&code);
- c << INDENT << "Shiboken::Conversions::pythonToCppPointer(&" << cpythonType << ", pyIn, cppOut);";
+ c << INDENT << "Shiboken::Conversions::pythonToCppPointer(" << cpythonType << ", pyIn, cppOut);";
writePythonToCppFunction(s, code, sourceTypeName, targetTypeName);
// "Is convertible" function for the Python object to C++ pointer conversion.
- QString pyTypeCheck = QStringLiteral("PyObject_TypeCheck(pyIn, (PyTypeObject*)&%1)").arg(cpythonType);
+ QString pyTypeCheck = QStringLiteral("PyObject_TypeCheck(pyIn, (PyTypeObject*)%1)").arg(cpythonType);
writeIsPythonConvertibleToCppFunction(s, sourceTypeName, targetTypeName, pyTypeCheck, QString(), true);
s << endl;
@@ -1157,7 +1159,7 @@ void CppGenerator::writeConverterFunctions(QTextStream &s, const AbstractMetaCla
code.clear();
if (usePySideExtensions() && metaClass->isQObject())
{
- c << INDENT << "return PySide::getWrapperForQObject((" << typeName << "*)cppIn, &" << cpythonType << ");" << endl;
+ c << INDENT << "return PySide::getWrapperForQObject((" << typeName << "*)cppIn, " << cpythonType << ");" << endl;
} else {
c << INDENT << "PyObject* pyOut = (PyObject*)Shiboken::BindingManager::instance().retrieveWrapper(cppIn);" << endl;
c << INDENT << "if (pyOut) {" << endl;
@@ -1168,7 +1170,7 @@ void CppGenerator::writeConverterFunctions(QTextStream &s, const AbstractMetaCla
}
c << INDENT << '}' << endl;
c << INDENT << "const char* typeName = typeid(*((" << typeName << "*)cppIn)).name();" << endl;
- c << INDENT << "return Shiboken::Object::newObject(&" << cpythonType;
+ c << INDENT << "return Shiboken::Object::newObject(" << cpythonType;
c << ", const_cast<void*>(cppIn), false, false, typeName);";
}
std::swap(targetTypeName, sourceTypeName);
@@ -1197,7 +1199,7 @@ void CppGenerator::writeConverterFunctions(QTextStream &s, const AbstractMetaCla
else
computedWrapperName = wrapperName(classContext.preciseType());
- c << INDENT << "return Shiboken::Object::newObject(&" << cpythonType << ", new ::" << computedWrapperName;
+ c << INDENT << "return Shiboken::Object::newObject(" << cpythonType << ", new ::" << computedWrapperName;
c << "(*((" << typeName << "*)cppIn)), true, true);";
writeCppToPythonFunction(s, code, sourceTypeName, targetTypeName);
s << endl;
@@ -1329,7 +1331,7 @@ void CppGenerator::writeConverterRegister(QTextStream &s, const AbstractMetaClas
if (metaClass->isNamespace())
return;
s << INDENT << "// Register Converter" << endl;
- s << INDENT << "SbkConverter* converter = Shiboken::Conversions::createConverter(&";
+ s << INDENT << "SbkConverter* converter = Shiboken::Conversions::createConverter(";
s << cpythonTypeName(metaClass) << ',' << endl;
{
Indentation indent(INDENT);
@@ -2324,7 +2326,7 @@ void CppGenerator::writePythonToCppTypeConversion(QTextStream& s,
if (!defaultValue.isEmpty())
s << '{' << endl << INDENT;
- s << "if (Shiboken::Conversions::isImplicitConversion(reinterpret_cast<const SbkObjectType *>("
+ s << "if (Shiboken::Conversions::isImplicitConversion(reinterpret_cast<SbkObjectType *>("
<< cpythonTypeNameExt(type) << "), " << pythonToCppFunc << "))" << endl;
{
Indentation indent(INDENT);
@@ -2838,7 +2840,7 @@ void CppGenerator::writePythonToCppConversionFunctions(QTextStream& s,
if (toNative->sourceType())
inType = cpythonTypeNameExt(toNative->sourceType());
else
- inType = QString::fromLatin1("(&%1_Type)").arg(toNative->sourceTypeName());
+ inType = QString::fromLatin1("(%1_TypeF())").arg(toNative->sourceTypeName());
code.replace(QLatin1String("%INTYPE"), inType);
code.replace(QLatin1String("%OUTTYPE"), targetType->qualifiedCppName());
code.replace(QLatin1String("%in"), QLatin1String("pyIn"));
@@ -3698,24 +3700,20 @@ void CppGenerator::writeClassDefinition(QTextStream &s,
}
if (!metaClass->baseClass())
- baseClassName = QLatin1String("reinterpret_cast<PyTypeObject*>(&SbkObject_Type)");
+ baseClassName = QLatin1String("reinterpret_cast<PyTypeObject*>(SbkObject_TypeF())");
bool onlyPrivCtor = !metaClass->hasNonPrivateConstructor();
const AbstractMetaClass *qCoreApp = AbstractMetaClass::findClass(classes(), QLatin1String("QCoreApplication"));
const bool isQApp = qCoreApp != Q_NULLPTR && metaClass->inheritsFrom(qCoreApp);
+ tp_flags = QLatin1String("Py_TPFLAGS_DEFAULT|Py_TPFLAGS_BASETYPE|Py_TPFLAGS_CHECKTYPES");
if (metaClass->isNamespace() || metaClass->hasPrivateDestructor()) {
- tp_flags = QLatin1String("Py_TPFLAGS_DEFAULT|Py_TPFLAGS_CHECKTYPES");
tp_dealloc = metaClass->hasPrivateDestructor() ?
- QLatin1String("SbkDeallocWrapperWithPrivateDtor") : QLatin1String("0");
+ QLatin1String("SbkDeallocWrapperWithPrivateDtor") :
+ QLatin1String("SbkDummyDealloc /* PYSIDE-595: Prevent replacement of \"0\" with subtype_dealloc. */");
tp_init = QLatin1String("0");
} else {
- if (onlyPrivCtor)
- tp_flags = QLatin1String("Py_TPFLAGS_DEFAULT|Py_TPFLAGS_CHECKTYPES");
- else
- tp_flags = QLatin1String("Py_TPFLAGS_DEFAULT|Py_TPFLAGS_BASETYPE|Py_TPFLAGS_CHECKTYPES");
-
QString deallocClassName;
if (shouldGenerateCppWrapper(metaClass))
deallocClassName = wrapperName(metaClass);
@@ -3741,7 +3739,21 @@ void CppGenerator::writeClassDefinition(QTextStream &s,
}
if (metaClass->hasPrivateDestructor() || onlyPrivCtor) {
- tp_new = QLatin1String("0");
+ // tp_flags = QLatin1String("Py_TPFLAGS_DEFAULT|Py_TPFLAGS_CHECKTYPES");
+ // This is not generally possible, because PySide does not care about
+ // privacy the same way. This worked before the heap types were used,
+ // because inheritance is not really checked for static types.
+ // Instead, we check this at runtime, see SbkObjectTypeTpNew.
+ if (metaClass->fullName().startsWith(QLatin1String("PySide2.Qt"))) {
+ // PYSIDE-595: No idea how to do non-inheritance correctly.
+ // Since that is only relevant in shiboken, I used a shortcut for
+ // PySide.
+ tp_new = QLatin1String("SbkObjectTpNew");
+ }
+ else {
+ tp_new = QLatin1String("SbkDummyNew /* PYSIDE-595: Prevent replacement "
+ "of \"0\" with base->tp_new. */");
+ }
tp_flags.append(QLatin1String("|Py_TPFLAGS_HAVE_GC"));
}
else if (isQApp) {
@@ -3782,6 +3794,9 @@ void CppGenerator::writeClassDefinition(QTextStream &s,
s << endl;
}
+ s << "// Class Definition -----------------------------------------------" << endl;
+ s << "extern \"C\" {" << endl;
+
if (!metaClass->typeEntry()->hashFunction().isEmpty())
tp_hash = QLatin1Char('&') + cpythonBaseName(metaClass) + QLatin1String("_HashFunc");
@@ -3789,83 +3804,65 @@ void CppGenerator::writeClassDefinition(QTextStream &s,
if (callOp && !callOp->isModifiedRemoved())
tp_call = QLatin1Char('&') + cpythonFunctionName(callOp);
- s << "// Class Definition -----------------------------------------------" << endl;
- s << "extern \"C\" {" << endl;
-
- if (supportsNumberProtocol(metaClass)) {
- s << "static PyNumberMethods " << className + QLatin1String("_TypeAsNumber") << ";" << endl;
- s << endl;
- }
-
- if (supportsSequenceProtocol(metaClass)) {
- s << "static PySequenceMethods " << className + QLatin1String("_TypeAsSequence") << ";" << endl;
- s << endl;
- }
-
- if (supportsMappingProtocol(metaClass)) {
- s << "static PyMappingMethods " << className + QLatin1String("_TypeAsMapping") << ";" << endl;
- s << endl;
- }
-
- s << "static SbkObjectType " << className + QLatin1String("_Type") << " = { { {" << endl;
- s << INDENT << "PyVarObject_HEAD_INIT(&SbkObjectType_Type, 0)" << endl;
QString computedClassTargetFullName;
if (!classContext.forSmartPointer())
computedClassTargetFullName = getClassTargetFullName(metaClass);
else
computedClassTargetFullName = getClassTargetFullName(classContext.preciseType());
- s << INDENT << "/*tp_name*/ \"" << computedClassTargetFullName << "\"," << endl;
- s << INDENT << "/*tp_basicsize*/ sizeof(SbkObject)," << endl;
- s << INDENT << "/*tp_itemsize*/ 0," << endl;
- s << INDENT << "/*tp_dealloc*/ " << tp_dealloc << ',' << endl;
- s << INDENT << "/*tp_print*/ 0," << endl;
- s << INDENT << "/*tp_getattr*/ 0," << endl;
- s << INDENT << "/*tp_setattr*/ 0," << endl;
- s << INDENT << "/*tp_compare*/ 0," << endl;
- s << INDENT << "/*tp_repr*/ " << m_tpFuncs[QLatin1String("__repr__")] << "," << endl;
- s << INDENT << "/*tp_as_number*/ 0," << endl;
- s << INDENT << "/*tp_as_sequence*/ 0," << endl;
- s << INDENT << "/*tp_as_mapping*/ 0," << endl;
- s << INDENT << "/*tp_hash*/ " << tp_hash << ',' << endl;
- s << INDENT << "/*tp_call*/ " << tp_call << ',' << endl;
- s << INDENT << "/*tp_str*/ " << m_tpFuncs[QLatin1String("__str__")] << ',' << endl;
- s << INDENT << "/*tp_getattro*/ " << tp_getattro << ',' << endl;
- s << INDENT << "/*tp_setattro*/ " << tp_setattro << ',' << endl;
- s << INDENT << "/*tp_as_buffer*/ 0," << endl;
- s << INDENT << "/*tp_flags*/ " << tp_flags << ',' << endl;
- s << INDENT << "/*tp_doc*/ 0," << endl;
- s << INDENT << "/*tp_traverse*/ " << className << "_traverse," << endl;
- s << INDENT << "/*tp_clear*/ " << className << "_clear," << endl;
- s << INDENT << "/*tp_richcompare*/ " << tp_richcompare << ',' << endl;
- s << INDENT << "/*tp_weaklistoffset*/ 0," << endl;
- s << INDENT << "/*tp_iter*/ " << m_tpFuncs[QLatin1String("__iter__")] << ',' << endl;
- s << INDENT << "/*tp_iternext*/ " << m_tpFuncs[QLatin1String("__next__")] << ',' << endl;
- s << INDENT << "/*tp_methods*/ " << className << "_methods," << endl;
- s << INDENT << "/*tp_members*/ 0," << endl;
- s << INDENT << "/*tp_getset*/ " << tp_getset << ',' << endl;
- s << INDENT << "/*tp_base*/ " << baseClassName << ',' << endl;
- s << INDENT << "/*tp_dict*/ 0," << endl;
- s << INDENT << "/*tp_descr_get*/ 0," << endl;
- s << INDENT << "/*tp_descr_set*/ 0," << endl;
- s << INDENT << "/*tp_dictoffset*/ 0," << endl;
- s << INDENT << "/*tp_init*/ " << tp_init << ',' << endl;
- s << INDENT << "/*tp_alloc*/ 0," << endl;
- s << INDENT << "/*tp_new*/ " << tp_new << ',' << endl;
- s << INDENT << "/*tp_free*/ 0," << endl;
- s << INDENT << "/*tp_is_gc*/ 0," << endl;
- s << INDENT << "/*tp_bases*/ 0," << endl;
- s << INDENT << "/*tp_mro*/ 0," << endl;
- s << INDENT << "/*tp_cache*/ 0," << endl;
- s << INDENT << "/*tp_subclasses*/ 0," << endl;
- s << INDENT << "/*tp_weaklist*/ 0" << endl;
- s << "}, }," << endl;
- s << INDENT << "/*priv_data*/ 0" << endl;
- s << "};" << endl;
QString suffix;
if (isObjectType(metaClass))
suffix = QLatin1String("*");
- s << "} //extern" << endl;
+ const QString typePtr = QLatin1String("_") + className
+ + QLatin1String("_Type");
+ s << "static SbkObjectType *" << typePtr << " = nullptr;" << endl;
+ s << "static SbkObjectType *" << className << "_TypeF(void)" << endl;
+ s << "{" << endl;
+ s << INDENT << "return " << typePtr << ";" << endl;
+ s << "}" << endl;
+ s << endl;
+ s << "static PyType_Slot " << className << "_slots[] = {" << endl;
+ s << INDENT << "{Py_tp_base, (void *)0}, // inserted by introduceWrapperType" << endl;
+ s << INDENT << "{Py_tp_dealloc, (void *)" << tp_dealloc << "}," << endl;
+ s << INDENT << "{Py_tp_repr, (void *)" << m_tpFuncs[QLatin1String("__repr__")] << "}," << endl;
+ s << INDENT << "{Py_tp_hash, (void *)" << tp_hash << "}," << endl;
+ s << INDENT << "{Py_tp_call, (void *)" << tp_call << "}," << endl;
+ s << INDENT << "{Py_tp_str, (void *)" << m_tpFuncs[QLatin1String("__str__")] << "}," << endl;
+ s << INDENT << "{Py_tp_getattro, (void *)" << tp_getattro << "}," << endl;
+ s << INDENT << "{Py_tp_setattro, (void *)" << tp_setattro << "}," << endl;
+ s << INDENT << "{Py_tp_traverse, (void *)" << className << "_traverse}," << endl;
+ s << INDENT << "{Py_tp_clear, (void *)" << className << "_clear}," << endl;
+ s << INDENT << "{Py_tp_richcompare, (void *)" << tp_richcompare << "}," << endl;
+ s << INDENT << "{Py_tp_iter, (void *)" << m_tpFuncs[QLatin1String("__iter__")] << "}," << endl;
+ s << INDENT << "{Py_tp_iternext, (void *)" << m_tpFuncs[QLatin1String("__next__")] << "}," << endl;
+ s << INDENT << "{Py_tp_methods, (void *)" << className << "_methods}," << endl;
+ s << INDENT << "{Py_tp_getset, (void *)" << tp_getset << "}," << endl;
+ s << INDENT << "{Py_tp_init, (void *)" << tp_init << "}," << endl;
+ s << INDENT << "{Py_tp_new, (void *)" << tp_new << "}," << endl;
+ if (supportsSequenceProtocol(metaClass)) {
+ s << INDENT << "// type supports sequence protocol" << endl;
+ writeTypeAsSequenceDefinition(s, metaClass);
+ }
+ if (supportsMappingProtocol(metaClass)) {
+ s << INDENT << "// type supports mapping protocol" << endl;
+ writeTypeAsMappingDefinition(s, metaClass);
+ }
+ if (supportsNumberProtocol(metaClass)) {
+ // This one must come last. See the function itself.
+ s << INDENT << "// type supports number protocol" << endl;
+ writeTypeAsNumberDefinition(s, metaClass);
+ }
+ s << INDENT << "{0, 0}" << endl;
+ s << "};" << endl;
+ s << "static PyType_Spec " << className << "_spec = {" << endl;
+ s << INDENT << "\"" << computedClassTargetFullName << "\"," << endl;
+ s << INDENT << "sizeof(SbkObject)," << endl;
+ s << INDENT << "0," << endl;
+ s << INDENT << tp_flags << "," << endl;
+ s << INDENT << className << "_slots" << endl;
+ s << "};" << endl;
+ s << endl;
+ s << "} //extern \"C\"" << endl;
}
void CppGenerator::writeMappingMethods(QTextStream &s,
@@ -3943,14 +3940,13 @@ void CppGenerator::writeTypeAsSequenceDefinition(QTextStream& s, const AbstractM
funcs[QLatin1String("__setitem__")] = baseName + QLatin1String("__setitem__");
}
- s << INDENT << "memset(&" << baseName << "_TypeAsSequence, 0, sizeof(PySequenceMethods));" << endl;
for (QHash<QString, QString>::const_iterator it = m_sqFuncs.cbegin(), end = m_sqFuncs.cend(); it != end; ++it) {
const QString& sqName = it.key();
if (funcs[sqName].isEmpty())
continue;
if (it.value() == QLatin1String("sq_slice"))
s << "#ifndef IS_PY3K" << endl;
- s << INDENT << baseName << "_TypeAsSequence." << it.value() << " = " << funcs[sqName] << ';' << endl;
+ s << INDENT << "{Py_" << it.value() << ", (void *)" << funcs[sqName] << "}," << endl;
if (it.value() == QLatin1String("sq_slice"))
s << "#endif" << endl;
}
@@ -3976,12 +3972,11 @@ void CppGenerator::writeTypeAsMappingDefinition(QTextStream& s, const AbstractMe
}
QString baseName = cpythonBaseName(metaClass);
- s << INDENT << "memset(&" << baseName << "_TypeAsMapping, 0, sizeof(PyMappingMethods));" << endl;
for (auto it = m_mpFuncs.cbegin(), end = m_mpFuncs.cend(); it != end; ++it) {
const QString &mpName = it.key();
if (funcs[mpName].isEmpty())
continue;
- s << INDENT << baseName << "_TypeAsMapping." << it.value() << " = " << funcs[mpName] << ';' << endl;
+ s << INDENT << "{Py_" << it.value() << ", (void *)" << funcs[mpName] << "}," << endl;
}
}
@@ -4029,7 +4024,6 @@ void CppGenerator::writeTypeAsNumberDefinition(QTextStream& s, const AbstractMet
nb[QLatin1String("bool")] = hasBoolCast(metaClass) ? baseName + QLatin1String("___nb_bool") : QString();
- s << INDENT << "memset(&" << baseName << "_TypeAsNumber, 0, sizeof(PyNumberMethods));" << endl;
for (QHash<QString, QString>::const_iterator it = m_nbFuncs.cbegin(), end = m_nbFuncs.cend(); it != end; ++it) {
const QString &nbName = it.key();
if (nb[nbName].isEmpty())
@@ -4038,21 +4032,29 @@ void CppGenerator::writeTypeAsNumberDefinition(QTextStream& s, const AbstractMet
// bool is special because the field name differs on Python 2 and 3 (nb_nonzero vs nb_bool)
// so a shiboken macro is used.
if (nbName == QLatin1String("bool")) {
- s << INDENT << "SBK_NB_BOOL(" << baseName << "_TypeAsNumber) = " << nb[nbName] << ';' << endl;
+ s << "#ifdef IS_PY3K" << endl;
+ s << INDENT << "{Py_nb_bool, (void *)" << nb[nbName] << "}," << endl;
+ s << "#else" << endl;
+ s << INDENT << "{Py_nb_nonzero, (void *)" << nb[nbName] << "}," << endl;
+ s << "#endif" << endl;
} else {
bool excludeFromPy3K = nbName == QLatin1String("__div__") || nbName == QLatin1String("__idiv__");
- if (excludeFromPy3K) {
- s << "#ifdef IS_PY3K" << endl;
- s << INDENT << "SBK_UNUSED(&" << nb[nbName] << ");" << endl;
- s << "#else" << endl;
- }
- s << INDENT << baseName << "_TypeAsNumber." << it.value() << " = " << nb[nbName] << ';' << endl;
- if (excludeFromPy3K)
- s << "#endif" << endl;
+ if (!excludeFromPy3K)
+ s << INDENT << "{Py_" << it.value() << ", (void *)" << nb[nbName] << "}," << endl;
}
}
- if (!nb[QLatin1String("__div__")].isEmpty())
- s << INDENT << baseName << "_TypeAsNumber.nb_true_divide = " << nb[QLatin1String("__div__")] << ';' << endl;
+ if (!nb[QLatin1String("__div__")].isEmpty()) {
+ s << INDENT << "{Py_nb_true_divide, (void *)" << nb[QLatin1String("__div__")] << "}," << endl;
+ s << "#ifndef IS_PY3K" << endl;
+ s << INDENT << "{Py_nb_divide, (void *)" << nb[QLatin1String("__div__")] << "}," << endl;
+ s << "#endif" << endl;
+ }
+ if (!nb[QLatin1String("__idiv__")].isEmpty()) {
+ s << INDENT << "// This function is unused in Python 3. We reference it here." << endl;
+ s << INDENT << "{0, (void *)" << nb[QLatin1String("__idiv__")] << "}," << endl;
+ s << INDENT << "// This list is ending at the first 0 entry." << endl;
+ s << INDENT << "// Therefore, we need to put the unused functions at the very end." << endl;
+ }
}
void CppGenerator::writeTpTraverseFunction(QTextStream& s, const AbstractMetaClass* metaClass)
@@ -4061,7 +4063,7 @@ void CppGenerator::writeTpTraverseFunction(QTextStream& s, const AbstractMetaCla
s << "static int ";
s << baseName << "_traverse(PyObject* " PYTHON_SELF_VAR ", visitproc visit, void* arg)" << endl;
s << '{' << endl;
- s << INDENT << "return reinterpret_cast<PyTypeObject*>(&SbkObject_Type)->tp_traverse(" PYTHON_SELF_VAR ", visit, arg);" << endl;
+ s << INDENT << "return PepType(reinterpret_cast<PyTypeObject*>(SbkObject_TypeF()))->tp_traverse(" PYTHON_SELF_VAR ", visit, arg);" << endl;
s << '}' << endl;
}
@@ -4071,7 +4073,7 @@ void CppGenerator::writeTpClearFunction(QTextStream& s, const AbstractMetaClass*
s << "static int ";
s << baseName << "_clear(PyObject* " PYTHON_SELF_VAR ")" << endl;
s << '{' << endl;
- s << INDENT << "return reinterpret_cast<PyTypeObject*>(&SbkObject_Type)->tp_clear(" PYTHON_SELF_VAR ");" << endl;
+ s << INDENT << "return PepType(reinterpret_cast<PyTypeObject*>(SbkObject_TypeF()))->tp_clear(" PYTHON_SELF_VAR ");" << endl;
s << '}' << endl;
}
@@ -4147,7 +4149,7 @@ void CppGenerator::writeGetterFunction(QTextStream &s,
{
Indentation indent(INDENT);
s << INDENT << "pyOut = reinterpret_cast<PyObject *>(Shiboken::Object::findColocatedChild("
- << "reinterpret_cast<SbkObject *>(self), reinterpret_cast<const SbkObjectType *>("
+ << "reinterpret_cast<SbkObject *>(self), reinterpret_cast<SbkObjectType *>("
<< cpythonTypeNameExt(fieldType)
<< ")));\n";
s << INDENT << "if (pyOut) {Py_IncRef(pyOut); return pyOut;}\n";
@@ -4474,7 +4476,7 @@ void CppGenerator::writeEnumInitialization(QTextStream& s, const AbstractMetaEnu
const EnumTypeEntry *enumTypeEntry = cppEnum->typeEntry();
QString enclosingObjectVariable;
if (enclosingClass)
- enclosingObjectVariable = QLatin1Char('&') + cpythonTypeName(enclosingClass);
+ enclosingObjectVariable = cpythonTypeName(enclosingClass);
else if (hasUpperEnclosingClass)
enclosingObjectVariable = QLatin1String("enclosingClass");
else
@@ -4488,8 +4490,8 @@ void CppGenerator::writeEnumInitialization(QTextStream& s, const AbstractMetaEnu
if (!cppEnum->isAnonymous()) {
FlagsTypeEntry* flags = enumTypeEntry->flags();
if (flags) {
- s << INDENT << cpythonTypeNameExt(flags) << " = PySide::QFlags::create(\"" << flags->flagsName() << "\", &"
- << cpythonEnumName(cppEnum) << "_as_number);" << endl;
+ s << INDENT << cpythonTypeNameExt(flags) << " = PySide::QFlags::create(\"" << flags->flagsName() << "\", "
+ << cpythonEnumName(cppEnum) << "_number_slots);" << endl;
}
enumVarTypeObj = cpythonTypeNameExt(enumTypeEntry);
@@ -4539,8 +4541,8 @@ void CppGenerator::writeEnumInitialization(QTextStream& s, const AbstractMetaEnu
{
Indentation indent(INDENT);
s << INDENT << "PyObject* anonEnumItem = PyInt_FromLong(" << enumValueText << ");" << endl;
- s << INDENT << "if (PyDict_SetItemString(reinterpret_cast<SbkObjectType *>(" << enclosingObjectVariable
- << ")->super.ht_type.tp_dict, \"" << enumValue->name() << "\", anonEnumItem) < 0)" << endl;
+ s << INDENT << "if (PyDict_SetItemString(PepType(reinterpret_cast<SbkObjectType *>(" << enclosingObjectVariable
+ << "))->tp_dict, \"" << enumValue->name() << "\", anonEnumItem) < 0)" << endl;
{
Indentation indent(INDENT);
s << INDENT << "return " << m_currentErrorCode << ';' << endl;
@@ -4609,7 +4611,7 @@ void CppGenerator::writeSignalInitialization(QTextStream& s, const AbstractMetaC
}
}
- s << INDENT << "PySide::Signal::registerSignals(&" << cpythonTypeName(metaClass) << ", &::"
+ s << INDENT << "PySide::Signal::registerSignals(" << cpythonTypeName(metaClass) << ", &::"
<< metaClass->qualifiedCppName() << "::staticMetaObject);" << endl;
}
@@ -4659,57 +4661,22 @@ void CppGenerator::writeFlagsNumberMethodsDefinition(QTextStream& s, const Abstr
{
QString cpythonName = cpythonEnumName(cppEnum);
- s << "static PyNumberMethods " << cpythonName << "_as_number = {" << endl;
- s << INDENT << "/*nb_add*/ 0," << endl;
- s << INDENT << "/*nb_subtract*/ 0," << endl;
- s << INDENT << "/*nb_multiply*/ 0," << endl;
- s << INDENT << "#ifndef IS_PY3K" << endl;
- s << INDENT << "/* nb_divide */ 0," << endl;
- s << INDENT << "#endif" << endl;
- s << INDENT << "/*nb_remainder*/ 0," << endl;
- s << INDENT << "/*nb_divmod*/ 0," << endl;
- s << INDENT << "/*nb_power*/ 0," << endl;
- s << INDENT << "/*nb_negative*/ 0," << endl;
- s << INDENT << "/*nb_positive*/ 0," << endl;
- s << INDENT << "/*nb_absolute*/ 0," << endl;
- s << INDENT << "/*nb_nonzero*/ " << cpythonName << "__nonzero," << endl;
- s << INDENT << "/*nb_invert*/ (unaryfunc)" << cpythonName << "___invert__," << endl;
- s << INDENT << "/*nb_lshift*/ 0," << endl;
- s << INDENT << "/*nb_rshift*/ 0," << endl;
- s << INDENT << "/*nb_and*/ (binaryfunc)" << cpythonName << "___and__," << endl;
- s << INDENT << "/*nb_xor*/ (binaryfunc)" << cpythonName << "___xor__," << endl;
- s << INDENT << "/*nb_or*/ (binaryfunc)" << cpythonName << "___or__," << endl;
- s << INDENT << "#ifndef IS_PY3K" << endl;
- s << INDENT << "/* nb_coerce */ 0," << endl;
- s << INDENT << "#endif" << endl;
- s << INDENT << "/*nb_int*/ " << cpythonName << "_long," << endl;
- s << INDENT << "#ifdef IS_PY3K" << endl;
- s << INDENT << "/*nb_reserved*/ 0," << endl;
- s << INDENT << "/*nb_float*/ 0," << endl;
- s << INDENT << "#else" << endl;
- s << INDENT << "/*nb_long*/ " << cpythonName << "_long," << endl;
- s << INDENT << "/*nb_float*/ 0," << endl;
- s << INDENT << "/*nb_oct*/ 0," << endl;
- s << INDENT << "/*nb_hex*/ 0," << endl;
- s << INDENT << "#endif" << endl;
- s << INDENT << "/*nb_inplace_add*/ 0," << endl;
- s << INDENT << "/*nb_inplace_subtract*/ 0," << endl;
- s << INDENT << "/*nb_inplace_multiply*/ 0," << endl;
- s << INDENT << "#ifndef IS_PY3K" << endl;
- s << INDENT << "/*nb_inplace_divide*/ 0," << endl;
- s << INDENT << "#endif" << endl;
- s << INDENT << "/*nb_inplace_remainder*/ 0," << endl;
- s << INDENT << "/*nb_inplace_power*/ 0," << endl;
- s << INDENT << "/*nb_inplace_lshift*/ 0," << endl;
- s << INDENT << "/*nb_inplace_rshift*/ 0," << endl;
- s << INDENT << "/*nb_inplace_and*/ 0," << endl;
- s << INDENT << "/*nb_inplace_xor*/ 0," << endl;
- s << INDENT << "/*nb_inplace_or*/ 0," << endl;
- s << INDENT << "/*nb_floor_divide*/ 0," << endl;
- s << INDENT << "/*nb_true_divide*/ 0," << endl;
- s << INDENT << "/*nb_inplace_floor_divide*/ 0," << endl;
- s << INDENT << "/*nb_inplace_true_divide*/ 0," << endl;
- s << INDENT << "/*nb_index*/ 0" << endl;
+ s << "static PyType_Slot " << cpythonName << "_number_slots[] = {" << endl;
+ s << "#ifdef IS_PY3K" << endl;
+ s << INDENT << "{Py_nb_bool, (void *)" << cpythonName << "__nonzero}," << endl;
+ s << "#else" << endl;
+ s << INDENT << "{Py_nb_nonzero, (void *)" << cpythonName << "__nonzero}," << endl;
+ s << INDENT << "{Py_nb_long, (void *)" << cpythonName << "_long}," << endl;
+ s << "#endif" << endl;
+ s << INDENT << "{Py_nb_invert, (void *)" << cpythonName << "___invert__}," << endl;
+ s << INDENT << "{Py_nb_and, (void *)" << cpythonName << "___and__}," << endl;
+ s << INDENT << "{Py_nb_xor, (void *)" << cpythonName << "___xor__}," << endl;
+ s << INDENT << "{Py_nb_or, (void *)" << cpythonName << "___or__}," << endl;
+ s << INDENT << "{Py_nb_int, (void *)" << cpythonName << "_long}," << endl;
+ s << "#ifndef IS_PY3K" << endl;
+ s << INDENT << "{Py_nb_long, (void *)" << cpythonName << "_long}," << endl;
+ s << "#endif" << endl;
+ s << INDENT << "{0, 0} // sentinel" << endl;
s << "};" << endl << endl;
}
@@ -4803,37 +4770,8 @@ void CppGenerator::writeClassRegister(QTextStream &s,
s << "(PyObject* " << enclosingObjectVariable << ")" << endl;
s << '{' << endl;
- if (supportsNumberProtocol(metaClass)) {
- s << INDENT << "// type has number operators" << endl;
- writeTypeAsNumberDefinition(s, metaClass);
- s << INDENT << pyTypeName << ".super.ht_type.tp_as_number = &" << pyTypeName << "AsNumber;" << endl;
- s << endl;
- }
-
- if (supportsSequenceProtocol(metaClass)) {
- s << INDENT << "// type supports sequence protocol" << endl;
- writeTypeAsSequenceDefinition(s, metaClass);
- s << INDENT << pyTypeName << ".super.ht_type.tp_as_sequence = &" << pyTypeName << "AsSequence;" << endl;
- s << endl;
- }
-
- if (supportsMappingProtocol(metaClass)) {
- s << INDENT << "// type supports mapping protocol" << endl;
- writeTypeAsMappingDefinition(s, metaClass);
- s << INDENT << pyTypeName << ".super.ht_type.tp_as_mapping = &" << pyTypeName << "AsMapping;" << endl;
- s << endl;
- }
-
- if (!classContext.forSmartPointer())
- s << INDENT << cpythonTypeNameExt(classTypeEntry) << endl;
- else
- s << INDENT << cpythonTypeNameExt(classContext.preciseType()) << endl;
-
- s << INDENT << " = reinterpret_cast<PyTypeObject*>(&" << pyTypeName << ");" << endl;
- s << endl;
-
// Multiple inheritance
- QString pyTypeBasesVariable = pyTypeName + QLatin1String("_bases");
+ QString pyTypeBasesVariable = chopType(pyTypeName) + QLatin1String("_Type_bases");
const AbstractMetaClassList baseClasses = getBaseClasses(metaClass);
if (metaClass->baseClassNames().size() > 1) {
s << INDENT << "PyObject* " << pyTypeBasesVariable << " = PyTuple_Pack(" << baseClasses.size() << ',' << endl;
@@ -4848,28 +4786,42 @@ void CppGenerator::writeClassRegister(QTextStream &s,
}
// Create type and insert it in the module or enclosing class.
- s << INDENT << "if (!Shiboken::ObjectType::introduceWrapperType(" << enclosingObjectVariable;
- QString typeName;
- if (!classContext.forSmartPointer())
- typeName = metaClass->name();
- else
- typeName = classContext.preciseType()->cppSignature();
-
- s << ", \"" << typeName << "\", \"";
+ const QString typePtr = QLatin1String("_") + chopType(pyTypeName)
+ + QLatin1String("_Type");
- // Original name
- if (!classContext.forSmartPointer())
- s << metaClass->qualifiedCppName() << (isObjectType(classTypeEntry) ? "*" : "");
- else
- s << classContext.preciseType()->cppSignature();
-
- s << "\"," << endl;
+ s << INDENT << typePtr << " = Shiboken::ObjectType::introduceWrapperType(" << endl;
{
Indentation indent(INDENT);
- s << INDENT << "&" << pyTypeName << "," << endl;
- s << INDENT << initFunctionName << "_SignaturesString";
+ // 1:enclosingObject
+ s << INDENT << enclosingObjectVariable << "," << endl;
+ QString typeName;
+ if (!classContext.forSmartPointer())
+ typeName = metaClass->name();
+ else
+ typeName = classContext.preciseType()->cppSignature();
+
+ // 2:typeName
+ s << INDENT << "\"" << typeName << "\"," << endl;
+
+ // 3:originalName
+ s << INDENT << "\"";
+ if (!classContext.forSmartPointer()) {
+ s << metaClass->qualifiedCppName();
+ if (isObjectType(classTypeEntry))
+ s << '*';
+ } else {
+ s << classContext.preciseType()->cppSignature();
+ }
+
+ s << "\"," << endl;
+ // 4:typeSpec
+ s << INDENT << '&' << chopType(pyTypeName) << "_spec," << endl;
- // Set destructor function
+ // 5:signaturesString
+ s << INDENT << initFunctionName << "_SignaturesString," << endl;
+
+ // 6:cppObjDtor
+ s << INDENT;
if (!metaClass->isNamespace() && !metaClass->hasPrivateDestructor()) {
QString dtorClassName = metaClass->qualifiedCppName();
if ((avoidProtectedHack() && metaClass->hasProtectedDestructor()) || classTypeEntry->isValue())
@@ -4877,28 +4829,37 @@ void CppGenerator::writeClassRegister(QTextStream &s,
if (classContext.forSmartPointer())
dtorClassName = wrapperName(classContext.preciseType());
- s << ", &Shiboken::callCppDestructor< ::" << dtorClassName << " >";
- } else if (metaClass->baseClass() || hasEnclosingClass) {
- s << ", 0";
+ s << "&Shiboken::callCppDestructor< ::" << dtorClassName << " >," << endl;
+ } else {
+ s << "0," << endl;
}
- // Base type
+ // 7:baseType
if (metaClass->baseClass()) {
- s << ", reinterpret_cast<SbkObjectType *>(" << cpythonTypeNameExt(metaClass->baseClass()->typeEntry()) << ')';
- // The other base types
- if (metaClass->baseClassNames().size() > 1)
- s << ", " << pyTypeBasesVariable;
- else if (hasEnclosingClass)
- s << ", 0";
- } else if (hasEnclosingClass) {
- s << ", 0, 0";
- }
- if (hasEnclosingClass)
- s << ", true";
- s << ")) {" << endl;
- s << INDENT << "return;" << endl;
+ s << INDENT << "reinterpret_cast<SbkObjectType *>("
+ << cpythonTypeNameExt(metaClass->baseClass()->typeEntry()) << ")," << endl;
+ } else {
+ s << INDENT << "0," << endl;
+ }
+
+ // 8:baseTypes
+ if (metaClass->baseClassNames().size() > 1)
+ s << INDENT << pyTypeBasesVariable << ',' << endl;
+ else
+ s << INDENT << "0," << endl;
+
+ // 9:isInnerClass
+ s << INDENT << (hasEnclosingClass ? "true" : "false") << endl;
}
- s << INDENT << '}' << endl << endl;
+ s << INDENT << ");" << endl;
+ s << INDENT << endl;
+
+ if (!classContext.forSmartPointer())
+ s << INDENT << cpythonTypeNameExt(classTypeEntry) << endl;
+ else
+ s << INDENT << cpythonTypeNameExt(classContext.preciseType()) << endl;
+ s << INDENT << " = reinterpret_cast<PyTypeObject*>(" << pyTypeName << ");" << endl;
+ s << endl;
// Register conversions for the type.
writeConverterRegister(s, metaClass, classContext);
@@ -4920,15 +4881,15 @@ void CppGenerator::writeClassRegister(QTextStream &s,
s << "Shiboken::ObjectType::getMultipleIheritanceFunction(reinterpret_cast<SbkObjectType*>(";
s << cpythonTypeNameExt(miClass->typeEntry()) << "));" << endl;
}
- s << INDENT << "Shiboken::ObjectType::setMultipleIheritanceFunction(&";
+ s << INDENT << "Shiboken::ObjectType::setMultipleInheritanceFunction(";
s << cpythonTypeName(metaClass) << ", func);" << endl;
- s << INDENT << "Shiboken::ObjectType::setCastFunction(&" << cpythonTypeName(metaClass);
+ s << INDENT << "Shiboken::ObjectType::setCastFunction(" << cpythonTypeName(metaClass);
s << ", &" << cpythonSpecialCastFunctionName(metaClass) << ");" << endl;
}
// Set typediscovery struct or fill the struct of another one
if (metaClass->isPolymorphic() && metaClass->baseClass()) {
- s << INDENT << "Shiboken::ObjectType::setTypeDiscoveryFunctionV2(&" << cpythonTypeName(metaClass);
+ s << INDENT << "Shiboken::ObjectType::setTypeDiscoveryFunctionV2(" << cpythonTypeName(metaClass);
s << ", &" << cpythonBaseName(metaClass) << "_typeDiscovery);" << endl << endl;
}
@@ -4948,7 +4909,7 @@ void CppGenerator::writeClassRegister(QTextStream &s,
for (const AbstractMetaField *field : fields) {
if (!field->isStatic())
continue;
- s << INDENT << QLatin1String("PyDict_SetItemString(") + cpythonTypeName(metaClass) + QLatin1String(".super.ht_type.tp_dict, \"");
+ s << INDENT << QLatin1String("PyDict_SetItemString(PepType(") + cpythonTypeName(metaClass) + QLatin1String(")->tp_dict, \"");
s << field->name() << "\", ";
writeToPythonConversion(s, field->type(), metaClass, metaClass->qualifiedCppName() + QLatin1String("::") + field->name());
s << ");" << endl;
@@ -4969,8 +4930,8 @@ void CppGenerator::writeClassRegister(QTextStream &s,
}
if (usePySideExtensions() && metaClass->isQObject()) {
- s << INDENT << "Shiboken::ObjectType::setSubTypeInitHook(&" << pyTypeName << ", &PySide::initQObjectSubType);" << endl;
- s << INDENT << "PySide::initDynamicMetaObject(&" << pyTypeName << ", &::" << metaClass->qualifiedCppName()
+ s << INDENT << "Shiboken::ObjectType::setSubTypeInitHook(" << pyTypeName << ", &PySide::initQObjectSubType);" << endl;
+ s << INDENT << "PySide::initDynamicMetaObject(" << pyTypeName << ", &::" << metaClass->qualifiedCppName()
<< "::staticMetaObject, sizeof(::" << metaClass->qualifiedCppName() << "));" << endl;
}
@@ -5163,7 +5124,7 @@ void CppGenerator::writeGetattroFunction(QTextStream& s, GeneratorContext &conte
s << INDENT << "if (Shiboken::Object::isUserType(" PYTHON_SELF_VAR ")) {" << endl;
{
Indentation indent(INDENT);
- s << INDENT << "PyObject* meth = PyDict_GetItem(" PYTHON_SELF_VAR "->ob_type->tp_dict, name);" << endl;
+ s << INDENT << "PyObject* meth = PyDict_GetItem(PepType(Py_TYPE(" PYTHON_SELF_VAR "))->tp_dict, name);" << endl;
s << INDENT << "if (meth)" << endl;
{
Indentation indent(INDENT);
@@ -5228,7 +5189,7 @@ void CppGenerator::writeGetattroFunction(QTextStream& s, GeneratorContext &conte
s << INDENT << "PyTypeObject *tp = Py_TYPE(self);" << endl;
s << INDENT << "PyErr_Format(PyExc_AttributeError," << endl;
s << INDENT << " \"'%.50s' object has no attribute '%.400s'\"," << endl;
- s << INDENT << " tp->tp_name, PyBytes_AS_STRING(name));" << endl;
+ s << INDENT << " PepType(tp)->tp_name, PyBytes_AS_STRING(name));" << endl;
s << INDENT << "return NULL;" << endl;
}
s << INDENT << "} else {" << endl;
@@ -5308,7 +5269,7 @@ bool CppGenerator::finishGeneration()
QString defineStr = QLatin1String("init_") + cls->qualifiedCppName().replace(QLatin1String("::"), QLatin1String("_"));
if (cls->enclosingClass() && (cls->enclosingClass()->typeEntry()->codeGeneration() != TypeEntry::GenerateForSubclass))
- defineStr += QLatin1Char('(') + cpythonTypeNameExt(cls->enclosingClass()->typeEntry()) + QLatin1String("->tp_dict);");
+ defineStr += QLatin1String("(PepType(") + cpythonTypeNameExt(cls->enclosingClass()->typeEntry()) + QLatin1String(")->tp_dict);");
else
defineStr += QLatin1String("(module);");
s_classPythonDefines << INDENT << defineStr << endl;
@@ -5854,10 +5815,12 @@ QString CppGenerator::writeReprFunction(QTextStream &s, GeneratorContext &contex
s << INDENT << "if (idx >= 0)" << endl;
{
Indentation indent(INDENT);
- s << INDENT << "str.replace(0, idx, Py_TYPE(self)->tp_name);" << endl;
+ s << INDENT << "str.replace(0, idx, PepType((Py_TYPE(self)))->tp_name);" << endl;
}
- s << INDENT << "PyObject* mod = PyDict_GetItemString(Py_TYPE(self)->tp_dict, \"__module__\");" << endl;
- s << INDENT << "if (mod)" << endl;
+ s << INDENT << "PyObject* mod = PyDict_GetItemString(PepType(Py_TYPE(self))->tp_dict, \"__module__\");" << endl;
+ // PYSIDE-595: The introduction of heap types has the side effect that the module name
+ // is always prepended to the type name. Therefore the strchr check:
+ s << INDENT << "if (mod && !strchr(str, '.'))" << endl;
{
Indentation indent(INDENT);
s << INDENT << "return Shiboken::String::fromFormat(\"<%s.%s at %p>\", Shiboken::String::toCString(mod), str.constData(), self);" << endl;
diff --git a/sources/shiboken2/generator/shiboken2/shibokengenerator.cpp b/sources/shiboken2/generator/shiboken2/shibokengenerator.cpp
index 6165ef00..976b3414 100644
--- a/sources/shiboken2/generator/shiboken2/shibokengenerator.cpp
+++ b/sources/shiboken2/generator/shiboken2/shibokengenerator.cpp
@@ -804,7 +804,7 @@ QString ShibokenGenerator::cpythonTypeName(const AbstractMetaClass* metaClass)
QString ShibokenGenerator::cpythonTypeName(const TypeEntry* type)
{
- return cpythonBaseName(type) + QLatin1String("_Type");
+ return cpythonBaseName(type) + QLatin1String("_TypeF()");
}
QString ShibokenGenerator::cpythonTypeNameExt(const TypeEntry* type)
@@ -838,7 +838,7 @@ QString ShibokenGenerator::converterObject(const TypeEntry* type)
if (isCppPrimitive(type))
return QString::fromLatin1("Shiboken::Conversions::PrimitiveTypeConverter<%1>()").arg(type->qualifiedCppName());
if (isWrapperType(type) || type->isEnum() || type->isFlags())
- return QString::fromLatin1("SBK_CONVERTER(%1)").arg(cpythonTypeNameExt(type));
+ return QString::fromLatin1("*PepType_SGTP(%1)->converter").arg(cpythonTypeNameExt(type));
if (type->isArray()) {
qDebug() << "Warning: no idea how to handle the Qt5 type " << type->qualifiedCppName();
@@ -1164,7 +1164,7 @@ QString ShibokenGenerator::cpythonCheckFunction(const AbstractMetaType* metaType
if (isPointerToWrapperType(type)) {
typeCheck += QString::fromLatin1("checkSequenceTypes(%1, ").arg(cpythonTypeNameExt(type));
} else if (isWrapperType(type)) {
- typeCheck += QLatin1String("convertibleSequenceTypes(reinterpret_cast<const SbkObjectType *>(");
+ typeCheck += QLatin1String("convertibleSequenceTypes(reinterpret_cast<SbkObjectType *>(");
typeCheck += cpythonTypeNameExt(type);
typeCheck += QLatin1String("), ");
} else {
@@ -1287,7 +1287,7 @@ QString ShibokenGenerator::cpythonIsConvertibleFunction(const AbstractMetaType*
result += QLatin1String("isPythonToCppReferenceConvertible");
else
result += QLatin1String("isPythonToCppValueConvertible");
- result += QLatin1String("(reinterpret_cast<const SbkObjectType *>(")
+ result += QLatin1String("(reinterpret_cast<SbkObjectType *>(")
+ cpythonTypeNameExt(metaType) + QLatin1String("), ");
return result;
}
@@ -1341,7 +1341,7 @@ QString ShibokenGenerator::cpythonToPythonConversionFunction(const AbstractMetaT
else
conversion = QLatin1String("pointer");
QString result = QLatin1String("Shiboken::Conversions::") + conversion
- + QLatin1String("ToPython(reinterpret_cast<const SbkObjectType *>(")
+ + QLatin1String("ToPython(reinterpret_cast<SbkObjectType *>(")
+ cpythonTypeNameExt(type) + QLatin1String("), ");
if (conversion != QLatin1String("pointer"))
result += QLatin1Char('&');
@@ -1362,7 +1362,7 @@ QString ShibokenGenerator::cpythonToPythonConversionFunction(const TypeEntry* ty
if (isWrapperType(type)) {
const QString conversion = type->isValue() ? QLatin1String("copy") : QLatin1String("pointer");
QString result = QLatin1String("Shiboken::Conversions::") + conversion
- + QLatin1String("ToPython(reinterpret_cast<const SbkObjectType *>(") + cpythonTypeNameExt(type)
+ + QLatin1String("ToPython(reinterpret_cast<SbkObjectType *>(") + cpythonTypeNameExt(type)
+ QLatin1String("), ");
if (conversion != QLatin1String("pointer"))
result += QLatin1Char('&');
@@ -1625,7 +1625,7 @@ void ShibokenGenerator::processCodeSnip(QString& code, const AbstractMetaClass*
// Replace template variable by the Python Type object
// for the class context in which the variable is used.
code.replace(QLatin1String("%PYTHONTYPEOBJECT"),
- cpythonTypeName(context) + QLatin1String(".super.ht_type"));
+ cpythonTypeName(context) + QLatin1String("->type"));
code.replace(QLatin1String("%TYPE"), wrapperName(context));
code.replace(QLatin1String("%CPPTYPE"), context->name());
}
@@ -1856,7 +1856,7 @@ void ShibokenGenerator::writeCodeSnips(QTextStream& s,
// class implementing the method in which the code snip is written
if (func->isStatic()) {
code.replace(QLatin1String("%PYTHONTYPEOBJECT"),
- cpythonTypeName(func->implementingClass()) + QLatin1String(".super.ht_type"));
+ cpythonTypeName(func->implementingClass()) + QLatin1String("->type"));
} else {
code.replace(QLatin1String("%PYTHONTYPEOBJECT."), pySelf + QLatin1String("->ob_type->"));
code.replace(QLatin1String("%PYTHONTYPEOBJECT"), pySelf + QLatin1String("->ob_type"));
diff --git a/sources/shiboken2/libshiboken/CMakeLists.txt b/sources/shiboken2/libshiboken/CMakeLists.txt
index e87cf07f..b5ba78e1 100644
--- a/sources/shiboken2/libshiboken/CMakeLists.txt
+++ b/sources/shiboken2/libshiboken/CMakeLists.txt
@@ -48,7 +48,10 @@ threadstatesaver.cpp
shibokenbuffer.cpp
signature.cpp
qapp_macro.cpp
+pep384impl.cpp
voidptr.cpp
+typespec.cpp
+bufferprocs27.cpp
)
get_numpy_location()
@@ -89,9 +92,12 @@ install(FILES
threadstatesaver.h
shibokenbuffer.h
sbkpython.h
+ pep384impl.h
signature.h
qapp_macro.h
voidptr.h
+ typespec.h
+ bufferprocs27.h
"${CMAKE_CURRENT_BINARY_DIR}/sbkversion.h"
DESTINATION include/shiboken2${shiboken2_SUFFIX})
install(TARGETS libshiboken EXPORT shiboken2
diff --git a/sources/shiboken2/libshiboken/autodecref.h b/sources/shiboken2/libshiboken/autodecref.h
index 1f3f41ea..7b6aa47d 100644
--- a/sources/shiboken2/libshiboken/autodecref.h
+++ b/sources/shiboken2/libshiboken/autodecref.h
@@ -79,7 +79,9 @@ public:
/// Returns the pointer of the Python object being held.
inline PyObject* object() { return m_pyObj; }
inline operator PyObject*() { return m_pyObj; }
+#ifndef Py_LIMITED_API
inline operator PyTupleObject*() { return reinterpret_cast<PyTupleObject*>(m_pyObj); }
+#endif
inline operator bool() const { return m_pyObj != 0; }
inline PyObject* operator->() { return m_pyObj; }
diff --git a/sources/shiboken2/libshiboken/basewrapper.cpp b/sources/shiboken2/libshiboken/basewrapper.cpp
index 21f6933d..0e2712ec 100644
--- a/sources/shiboken2/libshiboken/basewrapper.cpp
+++ b/sources/shiboken2/libshiboken/basewrapper.cpp
@@ -66,55 +66,34 @@ 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 PyType_Slot SbkObjectType_Type_slots[] = {
+ {Py_tp_dealloc, (void *)SbkObjectTypeDealloc},
+ {Py_tp_setattro, (void *)PyObject_GenericSetAttr},
+ {Py_tp_base, (void *)&PyType_Type},
+ {Py_tp_alloc, (void *)PyType_GenericAlloc},
+ {Py_tp_new, (void *)SbkObjectTypeTpNew},
+ {Py_tp_free, (void *)PyObject_GC_Del},
+ {0, 0}
};
+static PyType_Spec SbkObjectType_Type_spec = {
+ "Shiboken.ObjectType",
+ 0, // basicsize (inserted later)
+ sizeof(PyMemberDef),
+ Py_TPFLAGS_DEFAULT|Py_TPFLAGS_BASETYPE,
+ SbkObjectType_Type_slots,
+};
+
+
+PyTypeObject *SbkObjectType_TypeF(void)
+{
+ static PyTypeObject *type = nullptr;
+ if (!type) {
+ SbkObjectType_Type_spec.basicsize =
+ PepHeapType_SIZE + sizeof(SbkObjectTypePrivate);
+ type = reinterpret_cast<PyTypeObject *>(PyType_FromSpec(&SbkObjectType_Type_spec));
+ }
+ return type;
+}
static PyObject *SbkObjectGetDict(PyObject* pObj, void *)
{
@@ -176,57 +155,36 @@ static int SbkObject_clear(PyObject* self)
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 PyType_Slot SbkObject_Type_slots[] = {
+ {Py_tp_dealloc, (void *)SbkDeallocWrapperWithPrivateDtor},
+ {Py_tp_traverse, (void *)SbkObject_traverse},
+ {Py_tp_clear, (void *)SbkObject_clear},
+ // unsupported: {Py_tp_weaklistoffset, (void *)offsetof(SbkObject, weakreflist)},
+ {Py_tp_getset, (void *)SbkObjectGetSetList},
+ // unsupported: {Py_tp_dictoffset, (void *)offsetof(SbkObject, ob_dict)},
+ {0, 0}
};
+static PyType_Spec SbkObject_Type_spec = {
+ "Shiboken.Object",
+ sizeof(SbkObject),
+ 0,
+ Py_TPFLAGS_DEFAULT|Py_TPFLAGS_BASETYPE|Py_TPFLAGS_HAVE_GC,
+ SbkObject_Type_slots,
+};
+
+
+SbkObjectType *SbkObject_TypeF(void)
+{
+ static PyTypeObject *type = nullptr;
+ if (!type) {
+ type = reinterpret_cast<PyTypeObject *>(PyType_FromSpec(&SbkObject_Type_spec));
+ Py_TYPE(type) = SbkObjectType_TypeF();
+ Py_INCREF(Py_TYPE(type));
+ PepType(type)->tp_weaklistoffset = offsetof(SbkObject, weakreflist);
+ PepType(type)->tp_dictoffset = offsetof(SbkObject, ob_dict);
+ }
+ return reinterpret_cast<SbkObjectType *>(type);
+}
static void SbkDeallocWrapperCommon(PyObject* pyObj, bool canDelete)
@@ -237,8 +195,8 @@ static void SbkDeallocWrapperCommon(PyObject* pyObj, bool canDelete)
// 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);
+ bool needTypeDecref = (PyType_GetSlot(pyType, Py_tp_dealloc) == SbkDeallocWrapper
+ || PyType_GetSlot(pyType, Py_tp_dealloc) == SbkDeallocWrapperWithPrivateDtor);
// Ensure that the GC is no longer tracking this object to avoid a
// possible reentrancy problem. Since there are multiple steps involved
@@ -257,10 +215,10 @@ static void SbkDeallocWrapperCommon(PyObject* pyObj, bool canDelete)
// 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) {
+ SbkObjectTypePrivate *sotp = PepType_SOTP(pyType);
+ if (sotp->is_multicpp) {
Shiboken::DeallocVisitor visitor(sbkObj);
- Shiboken::walkThroughClassHierarchy(pyObj->ob_type, &visitor);
+ Shiboken::walkThroughClassHierarchy(Py_TYPE(pyObj), &visitor);
} else {
void* cptr = sbkObj->d->cptr[0];
Shiboken::Object::deallocData(sbkObj, true);
@@ -268,7 +226,7 @@ static void SbkDeallocWrapperCommon(PyObject* pyObj, bool canDelete)
Shiboken::ThreadStateSaver threadSaver;
if (Py_IsInitialized())
threadSaver.save();
- sbkType->d->cpp_dtor(cptr);
+ sotp->cpp_dtor(cptr);
}
} else {
Shiboken::Object::deallocData(sbkObj, true);
@@ -297,91 +255,103 @@ void SbkDeallocWrapperWithPrivateDtor(PyObject* self)
void SbkObjectTypeDealloc(PyObject* pyObj)
{
- SbkObjectType* sbkType = reinterpret_cast<SbkObjectType*>(pyObj);
+ SbkObjectTypePrivate *sotp = PepType_SOTP(pyObj);
+ PyTypeObject *type = reinterpret_cast<PyTypeObject*>(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;
+ if (sotp) {
+ if (sotp->user_data && sotp->d_func) {
+ sotp->d_func(sotp->user_data);
+ sotp->user_data = nullptr;
}
- 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;
+ free(sotp->original_name);
+ sotp->original_name = nullptr;
+ if (!Shiboken::ObjectType::isUserType(type))
+ Shiboken::Conversions::deleteConverter(sotp->converter);
+ delete sotp;
+ sotp = nullptr;
}
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.
+
+ // PYSIDE-595: Also check if all bases allow inheritance.
+ // Before we changed to heap types, it was sufficient to remove the
+ // Py_TPFLAGS_BASETYPE flag. That does not work, because PySide does
+ // not respect this flag itself!
PyObject* name;
PyObject* pyBases;
PyObject* dict;
static const char* kwlist[] = { "name", "bases", "dict", 0};
- if (!PyArg_ParseTupleAndKeywords(args, kwds, "SO!O!:sbktype", (char**)kwlist,
+ 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++) {
+ for (int i=0, i_max=PyTuple_GET_SIZE(pyBases); i < i_max; i++) {
PyObject* baseType = PyTuple_GET_ITEM(pyBases, i);
+#ifndef IS_PY3K
if (PyClass_Check(baseType)) {
- PyErr_Format(PyExc_TypeError, "Invalid base class used in type %s. PySide only support multiple inheritance from python new style class.", metatype->tp_name);
+ PyErr_Format(PyExc_TypeError, "Invalid base class used in type %s. "
+ "PySide only support multiple inheritance from python new style class.", PepType(metatype)->tp_name);
return 0;
}
- }
#endif
+ if (PepType(reinterpret_cast<PyTypeObject*>(baseType))->tp_new == SbkDummyNew) {
+ // PYSIDE-595: A base class does not allow inheritance.
+ return SbkDummyNew(metatype, args, kwds);
+ }
+ }
// The meta type creates a new type when the Python programmer extends a wrapped C++ class.
- SbkObjectType* newType = reinterpret_cast<SbkObjectType*>(PyType_Type.tp_new(metatype, args, kwds));
+ newfunc type_new = reinterpret_cast<newfunc>(PepType(&PyType_Type)->tp_new);
+ SbkObjectType *newType = reinterpret_cast<SbkObjectType*>(type_new(metatype, args, kwds));
if (!newType)
return 0;
Shiboken::ObjectType::initPrivateData(newType);
- SbkObjectTypePrivate* d = newType->d;
+ SbkObjectTypePrivate *sotp = PepType_SOTP(newType);
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;
+ SbkObjectTypePrivate *parentType = PepType_SOTP(bases.front());
+ sotp->mi_offsets = parentType->mi_offsets;
+ sotp->mi_init = parentType->mi_init;
+ sotp->mi_specialcast = parentType->mi_specialcast;
+ sotp->type_discovery = parentType->type_discovery;
+ sotp->cpp_dtor = parentType->cpp_dtor;
+ sotp->is_multicpp = 0;
+ sotp->converter = parentType->converter;
} else {
- 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;
+ sotp->mi_offsets = nullptr;
+ sotp->mi_init = nullptr;
+ sotp->mi_specialcast = nullptr;
+ sotp->type_discovery = nullptr;
+ sotp->cpp_dtor = nullptr;
+ sotp->is_multicpp = 1;
+ sotp->converter = nullptr;
}
if (bases.size() == 1)
- d->original_name = strdup(bases.front()->d->original_name);
+ sotp->original_name = strdup(PepType_SOTP(bases.front())->original_name);
else
- d->original_name = strdup("object");
- d->user_data = 0;
- d->d_func = 0;
- d->is_user_type = 1;
+ sotp->original_name = strdup("object");
+ sotp->user_data = nullptr;
+ sotp->d_func = nullptr;
+ sotp->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);
+ if (PepType_SOTP(*it)->subtype_init)
+ PepType_SOTP(*it)->subtype_init(newType, args, kwds);
}
return reinterpret_cast<PyObject*>(newType);
@@ -392,18 +362,19 @@ static PyObject *_setupNew(SbkObject *self, PyTypeObject *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);
+ SbkObjectTypePrivate * sotp = PepType_SOTP(subtype);
+ int numBases = ((sotp && sotp->is_multicpp) ?
+ Shiboken::getNumberOfCppBaseClasses(subtype) : 1);
d->cptr = new void*[numBases];
- std::memset(d->cptr, 0, sizeof(void*)*numBases);
+ std::memset(d->cptr, 0, sizeof(void*) * size_t(numBases));
d->hasOwnership = 1;
d->containsCppWrapper = 0;
d->validCppObject = 0;
- d->parentInfo = 0;
- d->referredObjects = 0;
+ d->parentInfo = nullptr;
+ d->referredObjects = nullptr;
d->cppObjectCreated = 0;
- self->ob_dict = 0;
- self->weakreflist = 0;
+ self->ob_dict = nullptr;
+ self->weakreflist = nullptr;
self->d = d;
return reinterpret_cast<PyObject*>(self);
}
@@ -422,18 +393,37 @@ PyObject* SbkQAppTpNew(PyTypeObject* subtype, PyObject *, PyObject *)
// For qApp, we need to create a singleton Python object.
// We cannot track this with the GC, because it is a static variable!
- // Python2 has a weird handling of flags in derived classes that Python3
+ // Python 2 has a weird handling of flags in derived classes that Python 3
// does not have. Observed with bug_307.py.
// But it could theoretically also happen with Python3.
// Therefore we enforce that there is no GC flag, ever!
+
+ // PYSIDE-560:
+ // We avoid to use this in Python 3, because we have a hard time to get
+ // write access to these flags
+#ifndef IS_PY3K
if (PyType_HasFeature(subtype, Py_TPFLAGS_HAVE_GC)) {
subtype->tp_flags &= ~Py_TPFLAGS_HAVE_GC;
subtype->tp_free = PyObject_Del;
}
+#endif
SbkObject* self = reinterpret_cast<SbkObject*>(MakeSingletonQAppWrapper(subtype));
return self == 0 ? 0 : _setupNew(self, subtype);
}
+void
+SbkDummyDealloc(PyObject *)
+{}
+
+PyObject *
+SbkDummyNew(PyTypeObject *type, PyObject*, PyObject*)
+{
+ // PYSIDE-595: Give the same error as type_call does when tp_new is NULL.
+ PyErr_Format(PyExc_TypeError,
+ "cannot create '%.100s' instances ¯\\_(ツ)_/¯",
+ PepType(type)->tp_name);
+ return nullptr;
+}
} //extern "C"
@@ -464,16 +454,16 @@ static void decRefPyObjectList(const std::list<PyObject*> &pyObj, PyObject* skip
static void _walkThroughClassHierarchy(PyTypeObject* currentType, HierarchyVisitor* visitor)
{
- PyObject* bases = currentType->tp_bases;
+ PyObject* bases = PepType(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))) {
+ if (!PyType_IsSubtype(type, reinterpret_cast<PyTypeObject*>(SbkObject_TypeF()))) {
continue;
} else {
SbkObjectType* sbkType = reinterpret_cast<SbkObjectType*>(type);
- if (sbkType->d->is_user_type)
+ if (PepType_SOTP(sbkType)->is_user_type)
_walkThroughClassHierarchy(type, visitor);
else
visitor->visit(sbkType);
@@ -532,7 +522,7 @@ void DtorCallerVisitor::done()
for (; it != m_ptrs.end(); ++it) {
Shiboken::ThreadStateSaver threadSaver;
threadSaver.save();
- it->second->d->cpp_dtor(it->first);
+ PepType_SOTP(it->second)->cpp_dtor(it->first);
}
}
@@ -555,15 +545,17 @@ void init()
PyEval_InitThreads();
//Init private data
- Shiboken::ObjectType::initPrivateData(&SbkObject_Type);
+ Pep_Init();
+
+ Shiboken::ObjectType::initPrivateData(SbkObject_TypeF());
- if (PyType_Ready(&SbkEnumType_Type) < 0)
+ if (PyType_Ready(SbkEnumType_TypeF()) < 0)
Py_FatalError("[libshiboken] Failed to initialise Shiboken.SbkEnumType metatype.");
- if (PyType_Ready(&SbkObjectType_Type) < 0)
+ if (PyType_Ready(SbkObjectType_TypeF()) < 0)
Py_FatalError("[libshiboken] Failed to initialise Shiboken.BaseWrapperType metatype.");
- if (PyType_Ready(reinterpret_cast<PyTypeObject *>(&SbkObject_Type)) < 0)
+ if (PyType_Ready(reinterpret_cast<PyTypeObject *>(SbkObject_TypeF())) < 0)
Py_FatalError("[libshiboken] Failed to initialise Shiboken.BaseWrapper type.");
VoidPtr::init();
@@ -581,10 +573,10 @@ void setErrorAboutWrongArguments(PyObject* args, const char* funcName, const cha
if (i)
params += ", ";
PyObject* arg = PyTuple_GET_ITEM(args, i);
- params += arg->ob_type->tp_name;
+ params += PepType((Py_TYPE(arg)))->tp_name;
}
} else {
- params = args->ob_type->tp_name;
+ params = PepType((Py_TYPE(args)))->tp_name;
}
}
@@ -660,12 +652,12 @@ namespace ObjectType
bool checkType(PyTypeObject* type)
{
- return PyType_IsSubtype(type, reinterpret_cast<PyTypeObject*>(&SbkObject_Type)) != 0;
+ return PyType_IsSubtype(type, reinterpret_cast<PyTypeObject*>(SbkObject_TypeF())) != 0;
}
bool isUserType(PyTypeObject* type)
{
- return checkType(type) && reinterpret_cast<SbkObjectType*>(type)->d->is_user_type;
+ return checkType(type) && PepType_SOTP(type)->is_user_type;
}
bool canCallConstructor(PyTypeObject* myType, PyTypeObject* ctorType)
@@ -673,7 +665,7 @@ 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);
+ PyErr_Format(PyExc_TypeError, "%s isn't a direct base class of %s", PepType(ctorType)->tp_name, PepType(myType)->tp_name);
return false;
}
return true;
@@ -681,114 +673,133 @@ bool canCallConstructor(PyTypeObject* myType, PyTypeObject* ctorType)
bool hasCast(SbkObjectType* type)
{
- return type->d->mi_specialcast != 0;
+ return PepType_SOTP(type)->mi_specialcast != 0;
}
void* cast(SbkObjectType* sourceType, SbkObject* obj, PyTypeObject* targetType)
{
- return sourceType->d->mi_specialcast(Object::cppPointer(obj, targetType), reinterpret_cast<SbkObjectType*>(targetType));
+ return PepType_SOTP(sourceType)->mi_specialcast(Object::cppPointer(obj, targetType),
+ reinterpret_cast<SbkObjectType*>(targetType));
}
void setCastFunction(SbkObjectType* type, SpecialCastFunction func)
{
- type->d->mi_specialcast = func;
+ PepType_SOTP(type)->mi_specialcast = func;
}
-void setOriginalName(SbkObjectType* self, const char* name)
+void setOriginalName(SbkObjectType* type, const char* name)
{
- if (self->d->original_name)
- free(self->d->original_name);
- self->d->original_name = strdup(name);
+ SbkObjectTypePrivate *sotp = PepType_SOTP(type);
+ if (sotp->original_name)
+ free(sotp->original_name);
+ sotp->original_name = strdup(name);
}
-const char* getOriginalName(SbkObjectType* self)
+const char* getOriginalName(SbkObjectType* type)
{
- return self->d->original_name;
+ return PepType_SOTP(type)->original_name;
}
-void setTypeDiscoveryFunctionV2(SbkObjectType* self, TypeDiscoveryFuncV2 func)
+void setTypeDiscoveryFunctionV2(SbkObjectType* type, TypeDiscoveryFuncV2 func)
{
- self->d->type_discovery = func;
+ PepType_SOTP(type)->type_discovery = func;
}
-void copyMultimpleheritance(SbkObjectType* self, SbkObjectType* other)
+void copyMultimpleheritance(SbkObjectType* type, 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;
+ PepType_SOTP(type)->mi_init = PepType_SOTP(other)->mi_init;
+ PepType_SOTP(type)->mi_offsets = PepType_SOTP(other)->mi_offsets;
+ PepType_SOTP(type)->mi_specialcast = PepType_SOTP(other)->mi_specialcast;
}
-void setMultipleIheritanceFunction(SbkObjectType* self, MultipleInheritanceInitFunction function)
+void setMultipleInheritanceFunction(SbkObjectType* type, MultipleInheritanceInitFunction function)
{
- self->d->mi_init = function;
+ PepType_SOTP(type)->mi_init = function;
}
-MultipleInheritanceInitFunction getMultipleIheritanceFunction(SbkObjectType* self)
+MultipleInheritanceInitFunction getMultipleIheritanceFunction(SbkObjectType* type)
{
- return self->d->mi_init;
+ return PepType_SOTP(type)->mi_init;
}
-void setDestructorFunction(SbkObjectType* self, ObjectDestructor func)
+void setDestructorFunction(SbkObjectType* type, ObjectDestructor func)
{
- self->d->cpp_dtor = func;
+ PepType_SOTP(type)->cpp_dtor = func;
}
-void initPrivateData(SbkObjectType* self)
+void initPrivateData(SbkObjectType* type)
{
- self->d = new SbkObjectTypePrivate;
- memset(self->d, 0, sizeof(SbkObjectTypePrivate));
+ PepType_SOTP(type) = new SbkObjectTypePrivate;
+ memset(PepType_SOTP(type), 0, sizeof(SbkObjectTypePrivate));
}
-bool introduceWrapperType(PyObject *enclosingObject,
- const char *typeName, const char *originalName,
- SbkObjectType *type,
- const char *signaturesString,
- ObjectDestructor cppObjDtor,
- SbkObjectType *baseType, PyObject *baseTypes,
- bool isInnerClass)
+SbkObjectType *
+introduceWrapperType(PyObject *enclosingObject,
+ const char *typeName,
+ const char *originalName,
+ PyType_Spec *typeSpec,
+ const char *signaturesString,
+ 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);
+ typeSpec->slots[0].pfunc = reinterpret_cast<void *>(baseType);
+ }
+ else {
+ typeSpec->slots[0].pfunc = reinterpret_cast<void *>(SbkObject_TypeF());
+ }
+ PyObject *heaptype = PyType_FromSpecWithBases(typeSpec, baseTypes);
+ Py_TYPE(heaptype) = SbkObjectType_TypeF();
+ Py_INCREF(Py_TYPE(heaptype));
+ SbkObjectType *type = reinterpret_cast<SbkObjectType *>(heaptype);
+ if (baseType) {
if (baseTypes) {
for (int i = 0; i < PySequence_Fast_GET_SIZE(baseTypes); ++i)
BindingManager::instance().addClassInheritance(reinterpret_cast<SbkObjectType *>(PySequence_Fast_GET_ITEM(baseTypes, i)), type);
- type->super.ht_type.tp_bases = baseTypes;
} else {
BindingManager::instance().addClassInheritance(baseType, type);
}
}
-
- // PySide-510
- // here is the single change to support signatures.
+ // PYSIDE-510: Here is the single change to support signatures.
if (SbkSpecial_Type_Ready(enclosingObject, reinterpret_cast<PyTypeObject *>(type), signaturesString) < 0)
- return false;
+ return nullptr;
- if (isInnerClass)
- return PyDict_SetItemString(enclosingObject, typeName, reinterpret_cast<PyObject *>(type)) == 0;
+ initPrivateData(type);
+ setOriginalName(type, originalName);
+ setDestructorFunction(type, cppObjDtor);
+
+ if (isInnerClass) {
+ if (PyDict_SetItemString(enclosingObject, typeName, reinterpret_cast<PyObject *>(type)) == 0)
+ return type;
+ else
+ return nullptr;
+ }
//PyModule_AddObject steals type's reference.
Py_INCREF(reinterpret_cast<PyObject *>(type));
- return PyModule_AddObject(enclosingObject, typeName, reinterpret_cast<PyObject *>(type)) == 0;
+ if (PyModule_AddObject(enclosingObject, typeName, reinterpret_cast<PyObject *>(type)) == 0) {
+ return type;
+ }
+ return nullptr;
}
-void setSubTypeInitHook(SbkObjectType* self, SubTypeInitHook func)
+void setSubTypeInitHook(SbkObjectType* type, SubTypeInitHook func)
{
- self->d->subtype_init = func;
+ PepType_SOTP(type)->subtype_init = func;
}
-void* getTypeUserData(SbkObjectType* self)
+void* getTypeUserData(SbkObjectType* type)
{
- return self->d->user_data;
+ return PepType_SOTP(type)->user_data;
}
-void setTypeUserData(SbkObjectType* self, void* userData, DeleteUserDataFunc d_func)
+void setTypeUserData(SbkObjectType* type, void* userData, DeleteUserDataFunc d_func)
{
- self->d->user_data = userData;
- self->d->d_func = d_func;
+ SbkObjectTypePrivate *sotp = PepType_SOTP(type);
+ sotp->user_data = userData;
+ sotp->d_func = d_func;
}
} // namespace ObjectType
@@ -801,12 +812,12 @@ static void recursive_invalidate(SbkObject* self, std::set<SbkObject*>& seen);
bool checkType(PyObject* pyObj)
{
- return ObjectType::checkType(pyObj->ob_type);
+ return ObjectType::checkType(Py_TYPE(pyObj));
}
bool isUserType(PyObject* pyObj)
{
- return ObjectType::isUserType(pyObj->ob_type);
+ return ObjectType::isUserType(Py_TYPE(pyObj));
}
Py_hash_t hash(PyObject* pyObj)
@@ -858,14 +869,15 @@ bool wasCreatedByPython(SbkObject* pyObj)
void callCppDestructors(SbkObject* pyObj)
{
- SbkObjectType* sbkType = reinterpret_cast<SbkObjectType*>(Py_TYPE(pyObj));
- if (sbkType->d->is_multicpp) {
+ PyTypeObject *type = Py_TYPE(pyObj);
+ SbkObjectTypePrivate * sotp = PepType_SOTP(type);
+ if (sotp->is_multicpp) {
Shiboken::DtorCallerVisitor visitor(pyObj);
- Shiboken::walkThroughClassHierarchy(Py_TYPE(pyObj), &visitor);
+ Shiboken::walkThroughClassHierarchy(type, &visitor);
} else {
Shiboken::ThreadStateSaver threadSaver;
threadSaver.save();
- sbkType->d->cpp_dtor(pyObj->d->cptr[0]);
+ sotp->cpp_dtor(pyObj->d->cptr[0]);
}
/* invalidate needs to be called before deleting pointer array because
@@ -916,7 +928,7 @@ 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))
+ if (!self->d->hasOwnership || Shiboken::Conversions::pythonTypeIsValueType(PepType_SOTP(selfType)->converter))
return;
// remove object ownership
@@ -1037,7 +1049,7 @@ void* cppPointer(SbkObject* pyObj, PyTypeObject* desiredType)
{
PyTypeObject* type = Py_TYPE(pyObj);
int idx = 0;
- if (reinterpret_cast<SbkObjectType*>(type)->d->is_multicpp)
+ if (PepType_SOTP(reinterpret_cast<SbkObjectType*>(type))->is_multicpp)
idx = getTypeIndexOnHierarchy(type, desiredType);
if (pyObj->d->cptr)
return pyObj->d->cptr[idx];
@@ -1057,8 +1069,9 @@ std::vector<void*> cppPointers(SbkObject* pyObj)
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);
+ PyTypeObject *type = Py_TYPE(sbkObj);
+ if (PepType_SOTP(type)->is_multicpp)
+ idx = getTypeIndexOnHierarchy(type, desiredType);
const bool alreadyInitialized = sbkObj->d->cptr[idx] != 0;
if (alreadyInitialized)
@@ -1073,19 +1086,21 @@ bool setCppPointer(SbkObject* sbkObj, PyTypeObject* desiredType, void* cptr)
bool isValid(PyObject* pyObj)
{
if (!pyObj || pyObj == Py_None
- || Py_TYPE(pyObj->ob_type) != &SbkObjectType_Type) {
+ || Py_TYPE(Py_TYPE(pyObj)) != SbkObjectType_TypeF()) {
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);
+ PyErr_Format(PyExc_RuntimeError, "'__init__' method of object's base class (%s) not called.",
+ PepType((Py_TYPE(pyObj)))->tp_name);
return false;
}
if (!priv->validCppObject) {
- PyErr_Format(PyExc_RuntimeError, "Internal C++ object (%s) already deleted.", pyObj->ob_type->tp_name);
+ PyErr_Format(PyExc_RuntimeError, "Internal C++ object (%s) already deleted.",
+ PepType((Py_TYPE(pyObj)))->tp_name);
return false;
}
@@ -1100,13 +1115,15 @@ bool isValid(SbkObject* pyObj, bool throwPyError)
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);
+ PyErr_Format(PyExc_RuntimeError, "Base constructor of the object (%s) not called.",
+ PepType((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);
+ PyErr_Format(PyExc_RuntimeError, "Internal C++ object (%s) already deleted.",
+ PepType((Py_TYPE(pyObj)))->tp_name);
return false;
}
@@ -1116,7 +1133,7 @@ bool isValid(SbkObject* pyObj, bool throwPyError)
bool isValid(PyObject* pyObj, bool throwPyError)
{
if (!pyObj || pyObj == Py_None ||
- !PyType_IsSubtype(pyObj->ob_type, reinterpret_cast<PyTypeObject*>(&SbkObject_Type))) {
+ !PyType_IsSubtype(Py_TYPE(pyObj), reinterpret_cast<PyTypeObject*>(SbkObject_TypeF()))) {
return true;
}
return isValid(reinterpret_cast<SbkObject*>(pyObj), throwPyError);
@@ -1384,24 +1401,25 @@ void deallocData(SbkObject* self, bool cleanup)
}
delete self->d; // PYSIDE-205: always delete d.
Py_XDECREF(self->ob_dict);
+
// PYSIDE-571: qApp is no longer allocated.
- if (PyObject_IS_GC((PyObject*)self))
- Py_TYPE(self)->tp_free(self);
+ if (PyObject_IS_GC(reinterpret_cast<PyObject*>(self)))
+ PepType(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);
+ SbkObjectTypePrivate *sotp = PepType_SOTP(Py_TYPE(wrapper));
+ if (sotp->user_data)
+ sotp->d_func(sotp->user_data);
- ob_type->d->d_func = d_func;
- ob_type->d->user_data = userData;
+ sotp->d_func = d_func;
+ sotp->user_data = userData;
}
void* getTypeUserData(SbkObject* wrapper)
{
- return reinterpret_cast<SbkObjectType*>(Py_TYPE(wrapper))->d->user_data;
+ return PepType_SOTP(Py_TYPE(wrapper))->user_data;
}
void keepReference(SbkObject* self, const char* key, PyObject* referredObject, bool append)
@@ -1483,7 +1501,7 @@ std::string info(SbkObject* 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 << PepType((reinterpret_cast<PyTypeObject*>(*it)))->tp_name << '/' << self->d->cptr[i] << ' ';
s << "\n";
}
else {
diff --git a/sources/shiboken2/libshiboken/basewrapper.h b/sources/shiboken2/libshiboken/basewrapper.h
index fc553cf8..755058e8 100644
--- a/sources/shiboken2/libshiboken/basewrapper.h
+++ b/sources/shiboken2/libshiboken/basewrapper.h
@@ -93,22 +93,34 @@ typedef void (*ObjectDestructor)(void*);
typedef void (*SubTypeInitHook)(SbkObjectType*, PyObject*, PyObject*);
-extern LIBSHIBOKEN_API PyTypeObject SbkObjectType_Type;
-extern LIBSHIBOKEN_API SbkObjectType SbkObject_Type;
+extern LIBSHIBOKEN_API PyTypeObject *SbkObjectType_TypeF(void);
+extern LIBSHIBOKEN_API SbkObjectType *SbkObject_TypeF(void);
struct SbkObjectTypePrivate;
/// PyTypeObject extended with C++ multiple inheritance information.
struct LIBSHIBOKEN_API SbkObjectType
{
- PyHeapTypeObject super;
- SbkObjectTypePrivate* d;
+ PepTypeObject type;
};
LIBSHIBOKEN_API PyObject* SbkObjectTpNew(PyTypeObject* subtype, PyObject*, PyObject*);
// the special case of a switchable singleton
LIBSHIBOKEN_API PyObject* SbkQAppTpNew(PyTypeObject *subtype, PyObject *args, PyObject *kwds);
+/**
+ * PYSIDE-595: Use a null deallocator instead of nullptr.
+ *
+ * When moving to heaptypes, we were struck by a special default behavior of
+ * PyType_FromSpecWithBases that inserts subtype_dealloc when tp_dealloc is
+ * nullptr. To prevent inserting this, we use a null deallocator that is there
+ * as a placeholder.
+ *
+ * The same holds for a null tp_new. We use one that raises the right error.
+ */
+LIBSHIBOKEN_API void SbkDummyDealloc(PyObject*);
+LIBSHIBOKEN_API PyObject *SbkDummyNew(PyTypeObject *type, PyObject*, PyObject*);
+
} // extern "C"
namespace Shiboken
@@ -173,7 +185,7 @@ LIBSHIBOKEN_API const char* getOriginalName(SbkObjectType* self);
LIBSHIBOKEN_API void setTypeDiscoveryFunctionV2(SbkObjectType* self, TypeDiscoveryFuncV2 func);
LIBSHIBOKEN_API void copyMultimpleheritance(SbkObjectType* self, SbkObjectType* other);
-LIBSHIBOKEN_API void setMultipleIheritanceFunction(SbkObjectType* self, MultipleInheritanceInitFunction func);
+LIBSHIBOKEN_API void setMultipleInheritanceFunction(SbkObjectType* self, MultipleInheritanceInitFunction func);
LIBSHIBOKEN_API MultipleInheritanceInitFunction getMultipleIheritanceFunction(SbkObjectType* self);
LIBSHIBOKEN_API void setDestructorFunction(SbkObjectType* self, ObjectDestructor func);
@@ -197,13 +209,15 @@ LIBSHIBOKEN_API void initPrivateData(SbkObjectType* self);
* 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,
- const char* signaturesString,
- ObjectDestructor cppObjDtor = 0,
- SbkObjectType* baseType = 0, PyObject* baseTypes = 0,
- bool isInnerClass = false);
+LIBSHIBOKEN_API SbkObjectType *introduceWrapperType(PyObject *enclosingObject,
+ const char *typeName,
+ const char *originalName,
+ PyType_Spec *typeSpec,
+ const char *signaturesString,
+ ObjectDestructor cppObjDtor,
+ SbkObjectType *baseType,
+ PyObject *baseTypes,
+ bool isInnerClass);
/**
* Set the subtype init hook for a type.
diff --git a/sources/shiboken2/libshiboken/bindingmanager.cpp b/sources/shiboken2/libshiboken/bindingmanager.cpp
index de3458ab..5a3283ab 100644
--- a/sources/shiboken2/libshiboken/bindingmanager.cpp
+++ b/sources/shiboken2/libshiboken/bindingmanager.cpp
@@ -83,8 +83,10 @@ public:
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";
+ for (; j != nodeList.end(); ++j) {
+ file << '"' << PepType(*j)->tp_name << "\" -> \""
+ << PepType(node1)->tp_name << "\"\n";
+ }
}
file << "}\n";
}
@@ -102,7 +104,10 @@ public:
return newType;
}
}
- void* typeFound = ((type->d && type->d->type_discovery) ? type->d->type_discovery(*cptr, baseType) : 0);
+ void *typeFound = nullptr;
+ if (PepType_SOTP(type) && PepType_SOTP(type)->type_discovery) {
+ typeFound = PepType_SOTP(type)->type_discovery(*cptr, baseType);
+ }
if (typeFound) {
// This "typeFound != type" is needed for backwards compatibility with old modules using a newer version of
// libshiboken because old versions of type_discovery function used to return a SbkObjectType* instead of
@@ -111,7 +116,7 @@ public:
*cptr = typeFound;
return type;
} else {
- return 0;
+ return nullptr;
}
}
};
@@ -128,7 +133,7 @@ static void showWrapperMap(const WrapperMap& wrapperMap)
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,
+ PepType((Py_TYPE(sbkObj)))->tp_name,
int(reinterpret_cast<const PyObject *>(sbkObj)->ob_refcnt));
}
fprintf(stderr, "-------------------------------\n");
@@ -210,7 +215,7 @@ bool BindingManager::hasWrapper(const void* cptr)
void BindingManager::registerWrapper(SbkObject* pyObj, void* cptr)
{
SbkObjectType* instanceType = reinterpret_cast<SbkObjectType*>(Py_TYPE(pyObj));
- SbkObjectTypePrivate* d = instanceType->d;
+ SbkObjectTypePrivate* d = PepType_SOTP(instanceType);
if (!d)
return;
@@ -231,7 +236,7 @@ void BindingManager::registerWrapper(SbkObject* pyObj, void* cptr)
void BindingManager::releaseWrapper(SbkObject* sbkObj)
{
SbkObjectType* sbkType = reinterpret_cast<SbkObjectType*>(Py_TYPE(sbkObj));
- SbkObjectTypePrivate* d = sbkType->d;
+ SbkObjectTypePrivate* d = PepType_SOTP(sbkType);
int numBases = ((d && d->is_multicpp) ? getNumberOfCppBaseClasses(Py_TYPE(sbkObj)) : 1);
void** cptrs = reinterpret_cast<SbkObject*>(sbkObj)->d->cptr;
@@ -278,17 +283,17 @@ PyObject* BindingManager::getOverride(const void* cptr, const char* 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)) {
+ && PyMethod_GET_SELF(method) == reinterpret_cast<PyObject*>(wrapper)) {
PyObject* defaultMethod;
- PyObject* mro = Py_TYPE(wrapper)->tp_mro;
+ PyObject* mro = PepType(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) {
+ if (PepType(parent)->tp_dict) {
+ defaultMethod = PyDict_GetItem(PepType(parent)->tp_dict, pyMethodName);
+ if (defaultMethod && PyMethod_GET_FUNCTION(method) != defaultMethod) {
Py_DECREF(pyMethodName);
return method;
}
diff --git a/sources/shiboken2/libshiboken/bufferprocs27.cpp b/sources/shiboken2/libshiboken/bufferprocs27.cpp
new file mode 100644
index 00000000..168a28a9
--- /dev/null
+++ b/sources/shiboken2/libshiboken/bufferprocs27.cpp
@@ -0,0 +1,397 @@
+/****************************************************************************
+**
+** Copyright (C) 2018 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of Qt for Python.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 3 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL3 included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 3 requirements
+** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 2.0 or (at your option) the GNU General
+** Public license version 3 or any later version approved by the KDE Free
+** Qt Foundation. The licenses are as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-2.0.html and
+** https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+/*****************************************************************************
+ *
+ * Copied from abstract.c
+ *
+ * Py_buffer has been replaced by Pep_buffer
+ *
+ */
+
+#ifdef Py_LIMITED_API
+
+#include "pep384impl.h"
+/* Buffer C-API for Python 3.0 */
+
+int
+PyObject_GetBuffer(PyObject *obj, Pep_buffer *view, int flags)
+{
+ PyBufferProcs *pb = PepType_AS_BUFFER(Py_TYPE(obj));
+
+ if (pb == NULL || pb->bf_getbuffer == NULL) {
+ PyErr_Format(PyExc_TypeError,
+ "a bytes-like object is required, not '%.100s'",
+ PepType((Py_TYPE(obj)))->tp_name);
+ return -1;
+ }
+ return (*pb->bf_getbuffer)(obj, view, flags);
+}
+
+static int
+_IsFortranContiguous(const Pep_buffer *view)
+{
+ Py_ssize_t sd, dim;
+ int i;
+
+ /* 1) len = product(shape) * itemsize
+ 2) itemsize > 0
+ 3) len = 0 <==> exists i: shape[i] = 0 */
+ if (view->len == 0) return 1;
+ if (view->strides == NULL) { /* C-contiguous by definition */
+ /* Trivially F-contiguous */
+ if (view->ndim <= 1) return 1;
+
+ /* ndim > 1 implies shape != NULL */
+ assert(view->shape != NULL);
+
+ /* Effectively 1-d */
+ sd = 0;
+ for (i=0; i<view->ndim; i++) {
+ if (view->shape[i] > 1) sd += 1;
+ }
+ return sd <= 1;
+ }
+
+ /* strides != NULL implies both of these */
+ assert(view->ndim > 0);
+ assert(view->shape != NULL);
+
+ sd = view->itemsize;
+ for (i=0; i<view->ndim; i++) {
+ dim = view->shape[i];
+ if (dim > 1 && view->strides[i] != sd) {
+ return 0;
+ }
+ sd *= dim;
+ }
+ return 1;
+}
+
+static int
+_IsCContiguous(const Pep_buffer *view)
+{
+ Py_ssize_t sd, dim;
+ int i;
+
+ /* 1) len = product(shape) * itemsize
+ 2) itemsize > 0
+ 3) len = 0 <==> exists i: shape[i] = 0 */
+ if (view->len == 0) return 1;
+ if (view->strides == NULL) return 1; /* C-contiguous by definition */
+
+ /* strides != NULL implies both of these */
+ assert(view->ndim > 0);
+ assert(view->shape != NULL);
+
+ sd = view->itemsize;
+ for (i=view->ndim-1; i>=0; i--) {
+ dim = view->shape[i];
+ if (dim > 1 && view->strides[i] != sd) {
+ return 0;
+ }
+ sd *= dim;
+ }
+ return 1;
+}
+
+int
+PyBuffer_IsContiguous(const Pep_buffer *view, char order)
+{
+
+ if (view->suboffsets != NULL) return 0;
+
+ if (order == 'C')
+ return _IsCContiguous(view);
+ else if (order == 'F')
+ return _IsFortranContiguous(view);
+ else if (order == 'A')
+ return (_IsCContiguous(view) || _IsFortranContiguous(view));
+ return 0;
+}
+
+
+void*
+PyBuffer_GetPointer(Pep_buffer *view, Py_ssize_t *indices)
+{
+ char* pointer;
+ int i;
+ pointer = (char *)view->buf;
+ for (i = 0; i < view->ndim; i++) {
+ pointer += view->strides[i]*indices[i];
+ if ((view->suboffsets != NULL) && (view->suboffsets[i] >= 0)) {
+ pointer = *((char**)pointer) + view->suboffsets[i];
+ }
+ }
+ return (void*)pointer;
+}
+
+
+void
+_Py_add_one_to_index_F(int nd, Py_ssize_t *index, const Py_ssize_t *shape)
+{
+ int k;
+
+ for (k=0; k<nd; k++) {
+ if (index[k] < shape[k]-1) {
+ index[k]++;
+ break;
+ }
+ else {
+ index[k] = 0;
+ }
+ }
+}
+
+void
+_Py_add_one_to_index_C(int nd, Py_ssize_t *index, const Py_ssize_t *shape)
+{
+ int k;
+
+ for (k=nd-1; k>=0; k--) {
+ if (index[k] < shape[k]-1) {
+ index[k]++;
+ break;
+ }
+ else {
+ index[k] = 0;
+ }
+ }
+}
+
+int
+PyBuffer_FromContiguous(Pep_buffer *view, void *buf, Py_ssize_t len, char fort)
+{
+ int k;
+ void (*addone)(int, Py_ssize_t *, const Py_ssize_t *);
+ Py_ssize_t *indices, elements;
+ char *src, *ptr;
+
+ if (len > view->len) {
+ len = view->len;
+ }
+
+ if (PyBuffer_IsContiguous(view, fort)) {
+ /* simplest copy is all that is needed */
+ memcpy(view->buf, buf, len);
+ return 0;
+ }
+
+ /* Otherwise a more elaborate scheme is needed */
+
+ /* view->ndim <= 64 */
+ indices = (Py_ssize_t *)PyMem_Malloc(sizeof(Py_ssize_t)*(view->ndim));
+ if (indices == NULL) {
+ PyErr_NoMemory();
+ return -1;
+ }
+ for (k=0; k<view->ndim;k++) {
+ indices[k] = 0;
+ }
+
+ if (fort == 'F') {
+ addone = _Py_add_one_to_index_F;
+ }
+ else {
+ addone = _Py_add_one_to_index_C;
+ }
+ src = (char *)buf; // patched by CT
+ /* XXX : This is not going to be the fastest code in the world
+ several optimizations are possible.
+ */
+ elements = len / view->itemsize;
+ while (elements--) {
+ ptr = (char *)PyBuffer_GetPointer(view, indices); // patched by CT
+ memcpy(ptr, src, view->itemsize);
+ src += view->itemsize;
+ addone(view->ndim, indices, view->shape);
+ }
+
+ PyMem_Free(indices);
+ return 0;
+}
+
+int PyObject_CopyData(PyObject *dest, PyObject *src)
+{
+ Pep_buffer view_dest, view_src;
+ int k;
+ Py_ssize_t *indices, elements;
+ char *dptr, *sptr;
+
+ if (!PyObject_CheckBuffer(dest) ||
+ !PyObject_CheckBuffer(src)) {
+ PyErr_SetString(PyExc_TypeError,
+ "both destination and source must be "\
+ "bytes-like objects");
+ return -1;
+ }
+
+ if (PyObject_GetBuffer(dest, &view_dest, PyBUF_FULL) != 0) return -1;
+ if (PyObject_GetBuffer(src, &view_src, PyBUF_FULL_RO) != 0) {
+ PyBuffer_Release(&view_dest);
+ return -1;
+ }
+
+ if (view_dest.len < view_src.len) {
+ PyErr_SetString(PyExc_BufferError,
+ "destination is too small to receive data from source");
+ PyBuffer_Release(&view_dest);
+ PyBuffer_Release(&view_src);
+ return -1;
+ }
+
+ if ((PyBuffer_IsContiguous(&view_dest, 'C') &&
+ PyBuffer_IsContiguous(&view_src, 'C')) ||
+ (PyBuffer_IsContiguous(&view_dest, 'F') &&
+ PyBuffer_IsContiguous(&view_src, 'F'))) {
+ /* simplest copy is all that is needed */
+ memcpy(view_dest.buf, view_src.buf, view_src.len);
+ PyBuffer_Release(&view_dest);
+ PyBuffer_Release(&view_src);
+ return 0;
+ }
+
+ /* Otherwise a more elaborate copy scheme is needed */
+
+ /* XXX(nnorwitz): need to check for overflow! */
+ indices = (Py_ssize_t *)PyMem_Malloc(sizeof(Py_ssize_t)*view_src.ndim);
+ if (indices == NULL) {
+ PyErr_NoMemory();
+ PyBuffer_Release(&view_dest);
+ PyBuffer_Release(&view_src);
+ return -1;
+ }
+ for (k=0; k<view_src.ndim;k++) {
+ indices[k] = 0;
+ }
+ elements = 1;
+ for (k=0; k<view_src.ndim; k++) {
+ /* XXX(nnorwitz): can this overflow? */
+ elements *= view_src.shape[k];
+ }
+ while (elements--) {
+ _Py_add_one_to_index_C(view_src.ndim, indices, view_src.shape);
+ dptr = (char *)PyBuffer_GetPointer(&view_dest, indices); // patched by CT
+ sptr = (char *)PyBuffer_GetPointer(&view_src, indices); // patched by CT
+ memcpy(dptr, sptr, view_src.itemsize);
+ }
+ PyMem_Free(indices);
+ PyBuffer_Release(&view_dest);
+ PyBuffer_Release(&view_src);
+ return 0;
+}
+
+void
+PyBuffer_FillContiguousStrides(int nd, Py_ssize_t *shape,
+ Py_ssize_t *strides, int itemsize,
+ char fort)
+{
+ int k;
+ Py_ssize_t sd;
+
+ sd = itemsize;
+ if (fort == 'F') {
+ for (k=0; k<nd; k++) {
+ strides[k] = sd;
+ sd *= shape[k];
+ }
+ }
+ else {
+ for (k=nd-1; k>=0; k--) {
+ strides[k] = sd;
+ sd *= shape[k];
+ }
+ }
+ return;
+}
+
+int
+PyBuffer_FillInfo(Pep_buffer *view, PyObject *obj, void *buf, Py_ssize_t len,
+ int readonly, int flags)
+{
+ if (view == NULL) {
+ PyErr_SetString(PyExc_BufferError,
+ "PyBuffer_FillInfo: view==NULL argument is obsolete");
+ return -1;
+ }
+
+ if (((flags & PyBUF_WRITABLE) == PyBUF_WRITABLE) &&
+ (readonly == 1)) {
+ PyErr_SetString(PyExc_BufferError,
+ "Object is not writable.");
+ return -1;
+ }
+
+ view->obj = obj;
+ if (obj)
+ Py_INCREF(obj);
+ view->buf = buf;
+ view->len = len;
+ view->readonly = readonly;
+ view->itemsize = 1;
+ view->format = NULL;
+ if ((flags & PyBUF_FORMAT) == PyBUF_FORMAT)
+ view->format = (char *)"B"; // patched by CT
+ view->ndim = 1;
+ view->shape = NULL;
+ if ((flags & PyBUF_ND) == PyBUF_ND)
+ view->shape = &(view->len);
+ view->strides = NULL;
+ if ((flags & PyBUF_STRIDES) == PyBUF_STRIDES)
+ view->strides = &(view->itemsize);
+ view->suboffsets = NULL;
+ view->internal = NULL;
+ return 0;
+}
+
+void
+PyBuffer_Release(Pep_buffer *view)
+{
+ PyObject *obj = view->obj;
+ PyBufferProcs *pb;
+ if (obj == NULL)
+ return;
+ pb = PepType_AS_BUFFER(Py_TYPE(obj));
+ if (pb && pb->bf_releasebuffer)
+ pb->bf_releasebuffer(obj, view);
+ view->obj = NULL;
+ Py_DECREF(obj);
+}
+
+#endif // Py_LIMITED_API
diff --git a/sources/shiboken2/libshiboken/bufferprocs27.h b/sources/shiboken2/libshiboken/bufferprocs27.h
new file mode 100644
index 00000000..83c4a475
--- /dev/null
+++ b/sources/shiboken2/libshiboken/bufferprocs27.h
@@ -0,0 +1,144 @@
+/****************************************************************************
+**
+** Copyright (C) 2018 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of Qt for Python.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 3 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL3 included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 3 requirements
+** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 2.0 or (at your option) the GNU General
+** Public license version 3 or any later version approved by the KDE Free
+** Qt Foundation. The licenses are as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-2.0.html and
+** https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+/*
+PSF LICENSE AGREEMENT FOR PYTHON 3.6.5¶
+1. This LICENSE AGREEMENT is between the Python Software Foundation ("PSF"), and
+ the Individual or Organization ("Licensee") accessing and otherwise using Python
+ 3.6.2 software in source or binary form and its associated documentation.
+
+2. Subject to the terms and conditions of this License Agreement, PSF hereby
+ grants Licensee a nonexclusive, royalty-free, world-wide license to reproduce,
+ analyze, test, perform and/or display publicly, prepare derivative works,
+ distribute, and otherwise use Python 3.6.2 alone or in any derivative
+ version, provided, however, that PSF's License Agreement and PSF's notice of
+ copyright, i.e., "Copyright © 2001-2017 Python Software Foundation; All Rights
+ Reserved" are retained in Python 3.6.2 alone or in any derivative version
+ prepared by Licensee.
+
+3. In the event Licensee prepares a derivative work that is based on or
+ incorporates Python 3.6.2 or any part thereof, and wants to make the
+ derivative work available to others as provided herein, then Licensee hereby
+ agrees to include in any such work a brief summary of the changes made to Python
+ 3.6.2.
+
+4. PSF is making Python 3.6.2 available to Licensee on an "AS IS" basis.
+ PSF MAKES NO REPRESENTATIONS OR WARRANTIES, EXPRESS OR IMPLIED. BY WAY OF
+ EXAMPLE, BUT NOT LIMITATION, PSF MAKES NO AND DISCLAIMS ANY REPRESENTATION OR
+ WARRANTY OF MERCHANTABILITY OR FITNESS FOR ANY PARTICULAR PURPOSE OR THAT THE
+ USE OF PYTHON 3.6.2 WILL NOT INFRINGE ANY THIRD PARTY RIGHTS.
+
+5. PSF SHALL NOT BE LIABLE TO LICENSEE OR ANY OTHER USERS OF PYTHON 3.6.2
+ FOR ANY INCIDENTAL, SPECIAL, OR CONSEQUENTIAL DAMAGES OR LOSS AS A RESULT OF
+ MODIFYING, DISTRIBUTING, OR OTHERWISE USING PYTHON 3.6.2, OR ANY DERIVATIVE
+ THEREOF, EVEN IF ADVISED OF THE POSSIBILITY THEREOF.
+
+6. This License Agreement will automatically terminate upon a material breach of
+ its terms and conditions.
+
+7. Nothing in this License Agreement shall be deemed to create any relationship
+ of agency, partnership, or joint venture between PSF and Licensee. This License
+ Agreement does not grant permission to use PSF trademarks or trade name in a
+ trademark sense to endorse or promote products or services of Licensee, or any
+ third party.
+
+8. By copying, installing or otherwise using Python 3.6.2, Licensee agrees
+ to be bound by the terms and conditions of this License Agreement.
+*/
+
+#ifndef BUFFER_REENABLE_H
+#define BUFFER_REENABLE_H
+
+/* buffer interface */
+// This has been renamed to Pep_buffer and will be used.
+typedef struct bufferinfo {
+ void *buf;
+ PyObject *obj; /* owned reference */
+ Py_ssize_t len;
+ Py_ssize_t itemsize; /* This is Py_ssize_t so it can be
+ pointed to by strides in simple case.*/
+ int readonly;
+ int ndim;
+ char *format;
+ Py_ssize_t *shape;
+ Py_ssize_t *strides;
+ Py_ssize_t *suboffsets;
+ void *internal;
+} Pep_buffer;
+
+typedef int (*getbufferproc)(PyObject *, Pep_buffer *, int);
+typedef void (*releasebufferproc)(PyObject *, Pep_buffer *);
+
+/* Maximum number of dimensions */
+#define PyBUF_MAX_NDIM 64
+
+/* Flags for getting buffers */
+#define PyBUF_SIMPLE 0
+#define PyBUF_WRITABLE 0x0001
+/* we used to include an E, backwards compatible alias */
+#define PyBUF_WRITEABLE PyBUF_WRITABLE
+#define PyBUF_FORMAT 0x0004
+#define PyBUF_ND 0x0008
+#define PyBUF_STRIDES (0x0010 | PyBUF_ND)
+#define PyBUF_C_CONTIGUOUS (0x0020 | PyBUF_STRIDES)
+#define PyBUF_F_CONTIGUOUS (0x0040 | PyBUF_STRIDES)
+#define PyBUF_ANY_CONTIGUOUS (0x0080 | PyBUF_STRIDES)
+#define PyBUF_INDIRECT (0x0100 | PyBUF_STRIDES)
+
+#define PyBUF_CONTIG (PyBUF_ND | PyBUF_WRITABLE)
+#define PyBUF_CONTIG_RO (PyBUF_ND)
+
+#define PyBUF_STRIDED (PyBUF_STRIDES | PyBUF_WRITABLE)
+#define PyBUF_STRIDED_RO (PyBUF_STRIDES)
+
+#define PyBUF_RECORDS (PyBUF_STRIDES | PyBUF_WRITABLE | PyBUF_FORMAT)
+#define PyBUF_RECORDS_RO (PyBUF_STRIDES | PyBUF_FORMAT)
+
+#define PyBUF_FULL (PyBUF_INDIRECT | PyBUF_WRITABLE | PyBUF_FORMAT)
+#define PyBUF_FULL_RO (PyBUF_INDIRECT | PyBUF_FORMAT)
+
+
+#define PyBUF_READ 0x100
+#define PyBUF_WRITE 0x200
+
+/* End buffer interface */
+LIBSHIBOKEN_API PyObject *PyMemoryView_FromBuffer(Pep_buffer *info);
+#define Py_buffer Pep_buffer
+
+#endif // BUFFER_REENABLE_H
diff --git a/sources/shiboken2/libshiboken/pep384impl.cpp b/sources/shiboken2/libshiboken/pep384impl.cpp
new file mode 100644
index 00000000..2707d371
--- /dev/null
+++ b/sources/shiboken2/libshiboken/pep384impl.cpp
@@ -0,0 +1,924 @@
+/****************************************************************************
+**
+** Copyright (C) 2018 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of Qt for Python.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 3 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL3 included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 3 requirements
+** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 2.0 or (at your option) the GNU General
+** Public license version 3 or any later version approved by the KDE Free
+** Qt Foundation. The licenses are as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-2.0.html and
+** https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "pep384impl.h"
+
+extern "C"
+{
+
+/**********************************************************************
+ **********************************************************************
+
+
+ The New Type API
+ ================
+
+ After converting everything but the "object.h" file, we could not
+ believe our eyes: it suddenly was clear that we would have no more
+ access to type objects, and even more scary that all types which we
+ use have to be heap types, only!
+
+ For PySide with it's intense use of heap type extensions in various
+ flavors, it seemed to be quite unsolvable. In the end, it was
+ nicely solved, but it took almost 3.5 months to get that right.
+
+ Before we see how this is done, we will explain the differences
+ between the APIs and their consequences.
+
+
+ The Interface
+ -------------
+
+ The old type API of Python knows static types and heap types.
+ Static types are written down as a declaration of a PyTypeObject
+ structure with all its fields filled in. Here is for example
+ the definition of the Python type "object":
+
+ PyTypeObject PyBaseObject_Type = {
+ PyVarObject_HEAD_INIT(&PyType_Type, 0)
+ "object", |* tp_name *|
+ sizeof(PyObject), |* tp_basicsize *|
+ 0, |* tp_itemsize *|
+ object_dealloc, |* tp_dealloc *|
+ 0, |* tp_print *|
+ 0, |* tp_getattr *|
+ 0, |* tp_setattr *|
+ 0, |* tp_reserved *|
+ object_repr, |* tp_repr *|
+ 0, |* tp_as_number *|
+ 0, |* tp_as_sequence *|
+ 0, |* tp_as_mapping *|
+ (hashfunc)_Py_HashPointer, |* tp_hash *|
+ 0, |* tp_call *|
+ object_str, |* tp_str *|
+ PyObject_GenericGetAttr, |* tp_getattro *|
+ PyObject_GenericSetAttr, |* tp_setattro *|
+ 0, |* tp_as_buffer *|
+ Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE, |* tp_flags *|
+ PyDoc_STR("object()\n--\n\nThe most base type"), |* tp_doc *|
+ 0, |* tp_traverse *|
+ 0, |* tp_clear *|
+ object_richcompare, |* tp_richcompare *|
+ 0, |* tp_weaklistoffset *|
+ 0, |* tp_iter *|
+ 0, |* tp_iternext *|
+ object_methods, |* tp_methods *|
+ 0, |* tp_members *|
+ object_getsets, |* tp_getset *|
+ 0, |* tp_base *|
+ 0, |* tp_dict *|
+ 0, |* tp_descr_get *|
+ 0, |* tp_descr_set *|
+ 0, |* tp_dictoffset *|
+ object_init, |* tp_init *|
+ PyType_GenericAlloc, |* tp_alloc *|
+ object_new, |* tp_new *|
+ PyObject_Del, |* tp_free *|
+ };
+
+ We can write the same structure in form of a PyType_Spec structure,
+ and there is even a tool that does this for us, but I had to fix a
+ few things because there is little support for this.
+
+ The tool is XXX go home and continue.....
+
+
+
+
+ The Transition To Simpler Types
+ ===============================
+
+ After all code has been converted to the limited API, there is the
+ PyHeapTypeObject remaining as a problem.
+
+ Why a problem? Well, all the type structures in shiboken use
+ special extra fields at the end of the heap type object. This
+ currently enforces knowledge at compile time about how large the
+ heap type object is. In a clean implementation, we would only use
+ the PyTypeObject itself and access the fields "behind" the type
+ by a pointer that is computed at runtime.
+
+
+ Excursion: PepTypeObject
+ ------------------------
+
+ Before we are going into details, let us motivate the existence of
+ the PepTypeObject, an alias to PyTypeObject:
+
+ Originally, we wanted to use PyTypeObject as an opaque type and
+ restrict ourselves to only use the access function PyType_GetSlot.
+ This function allows access to all fields which are supported by
+ the limited API.
+
+ But this is a restriction, because we get no access to tp_dict,
+ which we need to support the signature extension. But we can work
+ around that.
+
+ The real restriction is that PyType_GetSlot only works for heap
+ types. This makes the function quite useless, because we have
+ no access to PyType_Type, which is the most important type "type"
+ in Python. We need that for instance to compute the size of
+ PyHeapTypeObject dynamically.
+
+ With much effort, it is possible to clone PyType_Type as a heap
+ type. But due to a bug in the Pep 384 support, we need
+ access to the nb_index field of a normal type. Cloning does not
+ help because PyNumberMethods fields are not inherited.
+
+ After I realized this dead end, I changed the concept and did not
+ use PyType_GetSlot at all (except in function copyNumberMethods),
+ but created PepTypeObject as a remake of PyTypeObject with only
+ those fields defined that are needed in PySide.
+
+ Is this breakage of the limited API? I don't think so. A special
+ function runs on program startup that checks the correct position
+ of the fields of PepHeapType, although a change in those fields is
+ more than unlikely.
+ The really crucial thing is to no longer use PyHeapTypeObject
+ explicitly because that _does_ change its layout over time.
+
+
+ Diversification
+ ---------------
+
+ There are multiple SbkXXX structures which all use a "d" field
+ for their private data. This makes it not easy to find the right
+ fields when switching between types and objects.
+
+ struct LIBSHIBOKEN_API SbkObjectType
+ {
+ PyHeapTypeObject super;
+ SbkObjectTypePrivate *d;
+ };
+
+ struct LIBSHIBOKEN_API SbkObject
+ {
+ PyObject_HEAD
+ PyObject* ob_dict;
+ PyObject* weakreflist;
+ SbkObjectPrivate* d;
+ };
+
+ The first step was to rename the SbkObjectTypePrivate from "d" to
+ "sotp". It was chosen to be short but easy to remember.
+
+
+ Abstraction
+ -----------
+
+ After renaming the type extension pointers to "sotp", I replaced
+ them by function-like macros which did the special access "behind"
+ the types, instead of those explicit fields. For instance, the
+ expression
+
+ type->sotp->converter
+
+ became
+
+ PepType_SOTP(type)->converter
+
+ The macro expression can be seen here:
+
+ #define _genericTypeExtender(etype) \
+ (reinterpret_cast<char*>(etype) + \
+ (reinterpret_cast<PepTypeObject*>(&PyType_Type))->tp_basicsize)
+
+ #define PepType_SOTP(etype) \
+ (*reinterpret_cast<SbkObjectTypePrivate**>(_genericTypeExtender(etype)))
+
+ It looks complicated, but in the end there is only a single new
+ indirection via PyType_Type, which happens at runtime. This is the
+ key to fulfil what Pep 384 wants: No version-dependent fields.
+
+
+ Simplification
+ --------------
+
+ After all type extension fields were replaced by macro calls, we
+ could remove the version dependent definition
+
+ typedef struct _pepheaptypeobject {
+ union {
+ PepTypeObject ht_type;
+ void *opaque[PY_HEAPTYPE_SIZE];
+ };
+ } PepHeapTypeObject;
+
+ and the version dependent structure
+
+ struct LIBSHIBOKEN_API SbkObjectType
+ {
+ PepHeapTypeObject super;
+ SbkObjectTypePrivate *sotp;
+ };
+
+ could be replaced by the simplified
+
+ struct LIBSHIBOKEN_API SbkObjectType
+ {
+ PepTypeObject type;
+ };
+
+ which is no longer version-dependent.
+
+
+ Verification Of PepTypeObject
+ =============================
+
+ We have introduced PepTypeObject as a new alias for PyTypeObject,
+ and now we need to prove that we are allowed to do so.
+
+ When using the limited API as intended, then types are completely
+ opaque, and access is only through PyType_FromSpec and (from
+ version 3.5 upwards) through PyType_GetSlot.
+
+ Python then uses all the slot definitions in the type description
+ and produces a regular type object.
+
+
+ Unused Information
+ ------------------
+
+ But we know many things about types that are not explicitly said,
+ but they are inherently clear:
+
+ a) The basic structure of a type is always the same, regardless
+ if it is a static type or a heap type.
+
+ b) types are evolving very slowly, and a field is never replaced
+ by another field with different semantics.
+
+ Inherent rule a) gives us the following information: If we calculate
+ the offsets of the fields, then this info is also usable for non-
+ -heap types.
+
+ The validation checks if rule b) is still valid.
+
+
+ How it Works
+ ------------
+
+ The basic idea of the validation is to produce a new type using
+ PyType_FromSpec and to see where in the type structure these fields
+ show up. So we build a PyType_Slot structure with all the fields we
+ are using and make sure that these values are all unique in the
+ type.
+
+ Most fields are not investigated by PyType_FromSpec, and so we
+ simply used some numeric value. Some fields are interpreted, like
+ tp_members. This field must really be a PyMemberDef. And there are
+ tp_base and tp_bases which have to be type objects and lists
+ thereof. It was easiest to not produce these fields from scratch
+ but use them from the "type" object PyType_Type.
+
+ Then one would think to write a function that searches the known
+ values in the opaque type structure.
+
+ But we can do better and use optimistically the observation (b):
+ We simply use the PepTypeObject structure and assume that every
+ field lands exactly where we are awaiting it.
+
+ And that is the whole proof: If we find all the disjoint values at
+ the places where we expect them, thenthis is q.e.d. :)
+
+
+ About tp_dict
+ -------------
+
+ One word about the tp_dict field: This field is a bit special in
+ the proof, since it does not appear in the spec and cannot easily
+ be checked by "type.__dict__" because that creates a dictproxy
+ object. So how do we proove that is really the right dict?
+
+ We have to create that PyMethodDef structure anyway, and instead of
+ leaving it empty, we insert a dummy function. Then we ask the
+ tp_dict field if it has that object in it, and that's q.e.d.
+
+
+ *********/
+
+
+/*****************************************************************************
+ *
+ * Support for object.h
+ *
+ */
+
+/*
+ * Here is the verification code for PepTypeObject.
+ * We create a type object and check if its fields
+ * appear at the right offsets.
+ */
+
+#define make_dummy_int(x) (x * sizeof(void*))
+#define make_dummy(x) (reinterpret_cast<void*>(make_dummy_int(x)))
+
+#ifdef Py_LIMITED_API
+datetime_struc *PyDateTimeAPI = NULL;
+#endif
+
+static PyObject *
+dummy_func(PyObject *self, PyObject *args)
+{
+ Py_RETURN_NONE;
+}
+
+static struct PyMethodDef probe_methoddef[] = {
+ {"dummy", dummy_func, METH_NOARGS},
+ {0}
+};
+
+#define probe_tp_call make_dummy(1)
+#define probe_tp_str make_dummy(2)
+#define probe_tp_traverse make_dummy(3)
+#define probe_tp_clear make_dummy(4)
+#define probe_tp_methods probe_methoddef
+#define probe_tp_descr_get make_dummy(6)
+#define probe_tp_init make_dummy(7)
+#define probe_tp_alloc make_dummy(8)
+#define probe_tp_new make_dummy(9)
+#define probe_tp_free make_dummy(10)
+#define probe_tp_is_gc make_dummy(11)
+
+#define probe_tp_name "type.probe"
+#define probe_tp_basicsize make_dummy_int(42)
+
+static PyType_Slot typeprobe_slots[] = {
+ {Py_tp_call, probe_tp_call},
+ {Py_tp_str, probe_tp_str},
+ {Py_tp_traverse, probe_tp_traverse},
+ {Py_tp_clear, probe_tp_clear},
+ {Py_tp_methods, probe_tp_methods},
+ {Py_tp_descr_get, probe_tp_descr_get},
+ {Py_tp_init, probe_tp_init},
+ {Py_tp_alloc, probe_tp_alloc},
+ {Py_tp_new, probe_tp_new},
+ {Py_tp_free, probe_tp_free},
+ {Py_tp_is_gc, probe_tp_is_gc},
+ {0, 0}
+};
+static PyType_Spec typeprobe_spec = {
+ probe_tp_name,
+ probe_tp_basicsize,
+ 0,
+ Py_TPFLAGS_DEFAULT,
+ typeprobe_slots,
+};
+
+static void
+check_PepTypeObject_valid(void)
+{
+ PyObject *obtype = reinterpret_cast<PyObject*>(&PyType_Type);
+ PyTypeObject *probe_tp_base = reinterpret_cast<PyTypeObject*>(
+ PyObject_GetAttrString(obtype, "__base__"));
+ PyObject *probe_tp_bases = PyObject_GetAttrString(obtype, "__bases__");
+ PepTypeObject *check = reinterpret_cast<PepTypeObject*>(
+ PyType_FromSpecWithBases(&typeprobe_spec, probe_tp_bases));
+ PepTypeObject *typetype = reinterpret_cast<PepTypeObject*>(obtype);
+ PyObject *w = PyObject_GetAttrString(obtype, "__weakrefoffset__");
+ long probe_tp_weakrefoffset = PyLong_AsLong(w);
+ PyObject *d = PyObject_GetAttrString(obtype, "__dictoffset__");
+ long probe_tp_dictoffset = PyLong_AsLong(d);
+ PyObject *probe_tp_mro = PyObject_GetAttrString(obtype, "__mro__");
+ if (false
+ || probe_tp_name != check->tp_name
+ || probe_tp_basicsize != check->tp_basicsize
+ || probe_tp_call != check->tp_call
+ || probe_tp_str != check->tp_str
+ || probe_tp_traverse != check->tp_traverse
+ || probe_tp_clear != check->tp_clear
+ || probe_tp_weakrefoffset != typetype->tp_weaklistoffset
+ || probe_tp_methods != check->tp_methods
+ || probe_tp_base != typetype->tp_base
+ || !PyDict_Check(check->tp_dict)
+ || !PyDict_GetItemString(check->tp_dict, "dummy")
+ || probe_tp_descr_get != check->tp_descr_get
+ || probe_tp_dictoffset != typetype->tp_dictoffset
+ || probe_tp_init != check->tp_init
+ || probe_tp_alloc != check->tp_alloc
+ || probe_tp_new != check->tp_new
+ || probe_tp_free != check->tp_free
+ || probe_tp_is_gc != check->tp_is_gc
+ || probe_tp_bases != typetype->tp_bases
+ || probe_tp_mro != typetype->tp_mro)
+ Py_FatalError("The structure of type objects has changed!");
+ Py_DECREF(check);
+ Py_DECREF(probe_tp_base);
+ Py_DECREF(w);
+ Py_DECREF(d);
+ Py_DECREF(probe_tp_bases);
+ Py_DECREF(probe_tp_mro);
+}
+
+
+#ifdef Py_LIMITED_API
+
+// This structure is only here because Python 3 has an error.
+// I will fix that.
+
+typedef struct {
+ /* Number implementations must check *both*
+ arguments for proper type and implement the necessary conversions
+ in the slot functions themselves. */
+
+ binaryfunc nb_add;
+ binaryfunc nb_subtract;
+ binaryfunc nb_multiply;
+ binaryfunc nb_remainder;
+ binaryfunc nb_divmod;
+ ternaryfunc nb_power;
+ unaryfunc nb_negative;
+ unaryfunc nb_positive;
+ unaryfunc nb_absolute;
+ inquiry nb_bool;
+ unaryfunc nb_invert;
+ binaryfunc nb_lshift;
+ binaryfunc nb_rshift;
+ binaryfunc nb_and;
+ binaryfunc nb_xor;
+ binaryfunc nb_or;
+ unaryfunc nb_int;
+ void *nb_reserved; /* the slot formerly known as nb_long */
+ unaryfunc nb_float;
+
+ binaryfunc nb_inplace_add;
+ binaryfunc nb_inplace_subtract;
+ binaryfunc nb_inplace_multiply;
+ binaryfunc nb_inplace_remainder;
+ ternaryfunc nb_inplace_power;
+ binaryfunc nb_inplace_lshift;
+ binaryfunc nb_inplace_rshift;
+ binaryfunc nb_inplace_and;
+ binaryfunc nb_inplace_xor;
+ binaryfunc nb_inplace_or;
+
+ binaryfunc nb_floor_divide;
+ binaryfunc nb_true_divide;
+ binaryfunc nb_inplace_floor_divide;
+ binaryfunc nb_inplace_true_divide;
+
+ unaryfunc nb_index;
+
+ binaryfunc nb_matrix_multiply;
+ binaryfunc nb_inplace_matrix_multiply;
+} PyNumberMethods;
+
+// temporary structure until we have a generator for the offsets
+typedef struct _oldtypeobject {
+ PyVarObject ob_base;
+ void *X01; // const char *tp_name;
+ void *X02; // Py_ssize_t tp_basicsize;
+ void *X03; // Py_ssize_t tp_itemsize;
+ void *X04; // destructor tp_dealloc;
+ void *X05; // printfunc tp_print;
+ void *X06; // getattrfunc tp_getattr;
+ void *X07; // setattrfunc tp_setattr;
+ void *X08; // PyAsyncMethods *tp_as_async;
+ void *X09; // reprfunc tp_repr;
+ PyNumberMethods *tp_as_number;
+
+} PyOldTypeObject;
+
+// There is a bug in Python 3.6 that turned the Index_Check function
+// into a macro without taking care of the limited API.
+// This leads to the single problem that we don't have
+// access to PyLong_Type's nb_index field which is no heap type.
+// We cannot easily create this function by inheritance since it is
+// not inherited.
+//
+// Simple solution: Create the structure and write such a function.
+// Long term: Submit a patch to python.org .
+
+unaryfunc
+PepType_nb_index(PyTypeObject *type)
+{
+ return reinterpret_cast<PyOldTypeObject*>(type)->tp_as_number->nb_index;
+}
+
+int PyIndex_Check(PyObject *obj)
+{
+ PyOldTypeObject *type = reinterpret_cast<PyOldTypeObject*>(Py_TYPE(obj));
+ return type->tp_as_number != NULL &&
+ type->tp_as_number->nb_index != NULL;
+}
+
+/*****************************************************************************
+ *
+ * Support for unicodeobject.h
+ *
+ */
+
+char *
+_PepUnicode_AsString(PyObject *str)
+{
+ /*
+ * We need to keep the string alive but cannot borrow the Python object.
+ * Ugly easy way out: We re-code as an interned bytes string. This
+ * produces a pseudo-leak as long there are new strings.
+ * Typically, this function is used for name strings, and the dict size
+ * will not grow so much.
+ */
+#define STRINGIFY(x) #x
+#define TOSTRING(x) STRINGIFY(x)
+#define AT __FILE__ ":" TOSTRING(__LINE__)
+
+ static PyObject *cstring_dict = NULL;
+ if (cstring_dict == NULL) {
+ cstring_dict = PyDict_New();
+ if (cstring_dict == NULL)
+ Py_FatalError("Error in " AT);
+ }
+ PyObject *bytesStr = PyUnicode_AsEncodedString(str, "utf8", NULL);
+ PyObject *entry = PyDict_GetItem(cstring_dict, bytesStr);
+ if (entry == NULL) {
+ int e = PyDict_SetItem(cstring_dict, bytesStr, bytesStr);
+ if (e != 0)
+ Py_FatalError("Error in " AT);
+ entry = bytesStr;
+ }
+ else
+ Py_DECREF(bytesStr);
+ return PyBytes_AsString(entry);
+}
+
+/*****************************************************************************
+ *
+ * Support for longobject.h
+ *
+ */
+
+/*
+ * This is the original Python function _PyLong_AsInt() from longobject.c .
+ * We define it here because we are not allowed to use the function
+ * from Python with an underscore.
+ */
+
+/* Get a C int from an int object or any object that has an __int__
+ method. Return -1 and set an error if overflow occurs. */
+
+int
+_PepLong_AsInt(PyObject *obj)
+{
+ int overflow;
+ long result = PyLong_AsLongAndOverflow(obj, &overflow);
+ if (overflow || result > INT_MAX || result < INT_MIN) {
+ /* XXX: could be cute and give a different
+ message for overflow == -1 */
+ PyErr_SetString(PyExc_OverflowError,
+ "Python int too large to convert to C int");
+ return -1;
+ }
+ return (int)result;
+}
+
+/*****************************************************************************
+ *
+ * Support for pydebug.h
+ *
+ */
+static PyObject *sys_flags = NULL;
+
+int
+Pep_GetFlag(const char *name)
+{
+ static int initialized = 0;
+ int ret = -1;
+
+ if (!initialized) {
+ sys_flags = PySys_GetObject("flags");
+ // func gives no error if NULL is returned and does not incref.
+ Py_XINCREF(sys_flags);
+ initialized = 1;
+ }
+ if (sys_flags != NULL) {
+ PyObject *ob_ret = PyObject_GetAttrString(sys_flags, name);
+ if (ob_ret != NULL) {
+ long long_ret = PyLong_AsLong(ob_ret);
+ Py_DECREF(ob_ret);
+ ret = (int) long_ret;
+ }
+ }
+ return ret;
+}
+
+int
+Pep_GetVerboseFlag()
+{
+ static int initialized = 0;
+ static int verbose_flag = -1;
+
+ if (!initialized) {
+ verbose_flag = Pep_GetFlag("verbose");
+ if (verbose_flag != -1)
+ initialized = 1;
+ }
+ return verbose_flag;
+}
+
+/*****************************************************************************
+ *
+ * Support for code.h
+ *
+ */
+
+int
+PepCode_Get(PyCodeObject *co, const char *name)
+{
+ PyObject *ob = (PyObject *)co;
+ PyObject *ob_ret;
+ int ret = -1;
+
+ ob_ret = PyObject_GetAttrString(ob, name);
+ if (ob_ret != NULL) {
+ long long_ret = PyLong_AsLong(ob_ret);
+ Py_DECREF(ob_ret);
+ ret = (int) long_ret;
+ }
+ return ret;
+}
+
+/*****************************************************************************
+ *
+ * Support for datetime.h
+ *
+ */
+
+static PyTypeObject *dt_getCheck(const char *name)
+{
+ PyObject *op = PyObject_GetAttrString(PyDateTimeAPI->module, name);
+ if (op == NULL) {
+ fprintf(stderr, "datetime.%s not found\n", name);
+ Py_FatalError("aborting");
+ }
+ return (PyTypeObject *)op;
+}
+
+// init_DateTime is called earlier than our module init.
+// We use the provided PyDateTime_IMPORT machinery.
+datetime_struc *
+init_DateTime(void)
+{
+ static int initialized = 0;
+ if (!initialized) {
+ PyDateTimeAPI = (datetime_struc *)malloc(sizeof(datetime_struc));
+ if (PyDateTimeAPI == NULL)
+ Py_FatalError("PyDateTimeAPI malloc error, aborting");
+ PyDateTimeAPI->module = PyImport_ImportModule("datetime");
+ if (PyDateTimeAPI->module == NULL)
+ Py_FatalError("datetime module not found, aborting");
+ PyDateTimeAPI->DateType = dt_getCheck("date");
+ PyDateTimeAPI->DateTimeType = dt_getCheck("datetime");
+ PyDateTimeAPI->TimeType = dt_getCheck("time");
+ PyDateTimeAPI->DeltaType = dt_getCheck("timedelta");
+ PyDateTimeAPI->TZInfoType = dt_getCheck("tzinfo");
+ initialized = 1;
+ }
+ return PyDateTimeAPI;
+}
+
+int
+PyDateTime_Get(PyObject *ob, const char *name)
+{
+ PyObject *ob_ret;
+ int ret = -1;
+
+ ob_ret = PyObject_GetAttrString(ob, name);
+ if (ob_ret != NULL) {
+ long long_ret = PyLong_AsLong(ob_ret);
+ Py_DECREF(ob_ret);
+ ret = (int) long_ret;
+ }
+ return ret;
+}
+
+PyObject *
+PyDate_FromDate(int year, int month, int day)
+{
+ return PyObject_CallFunction((PyObject *)PyDateTimeAPI->DateType,
+ (char *)"(iii)", year, month, day);
+}
+
+PyObject *
+PyDateTime_FromDateAndTime(int year, int month, int day,
+ int hour, int min, int sec, int usec)
+{
+ return PyObject_CallFunction((PyObject *)PyDateTimeAPI->DateTimeType,
+ (char *)"(iiiiiii)", year, month, day,
+ hour, min, sec, usec);
+}
+
+PyObject *
+PyTime_FromTime(int hour, int min, int sec, int usec)
+{
+ return PyObject_CallFunction((PyObject *)PyDateTimeAPI->TimeType,
+ (char *)"(iiii)", hour, min, sec, usec);
+}
+
+/*****************************************************************************
+ *
+ * Support for pythonrun.h
+ *
+ */
+
+// Flags are ignored in these simple helpers.
+PyObject *
+PyRun_String(const char *str, int start, PyObject *globals, PyObject *locals)
+{
+ PyObject* code = Py_CompileString(str, "pyscript", start);
+ PyObject* ret = NULL;
+
+ if (code != NULL) {
+ ret = PyEval_EvalCode(code, globals, locals);
+ }
+ Py_XDECREF(code);
+ return ret;
+}
+
+// This is only a simple local helper that returns a computed variable.
+static PyObject *
+PepRun_GetResult(const char *command, const char *resvar)
+{
+ PyObject *d, *v, *res;
+
+ d = PyDict_New();
+ if (d == NULL || PyDict_SetItemString(d, "__builtins__",
+ PyEval_GetBuiltins()) < 0)
+ return NULL;
+ v = PyRun_String(command, Py_file_input, d, d);
+ res = v ? PyDict_GetItemString(d, resvar) : NULL;
+ Py_XDECREF(v);
+ Py_DECREF(d);
+ return res;
+}
+
+/*****************************************************************************
+ *
+ * Support for classobject.h
+ *
+ */
+
+PyTypeObject *PepMethod_TypePtr = NULL;
+
+static PyTypeObject *getMethodType(void)
+{
+ static const char prog[] =
+ "class _C:\n"
+ " def _m(self): pass\n"
+ "MethodType = type(_C()._m)\n";
+ return (PyTypeObject *) PepRun_GetResult(prog, "MethodType");
+}
+
+// We have no access to PyMethod_New and must call types.MethodType, instead.
+PyObject *
+PyMethod_New(PyObject *func, PyObject *self)
+{
+ return PyObject_CallFunction((PyObject *)PepMethod_TypePtr,
+ (char *)"(OO)", func, self);
+}
+
+PyObject *
+PyMethod_Function(PyObject *im)
+{
+ PyObject *ret = PyObject_GetAttrString(im, "__func__");
+
+ // We have to return a borrowed reference.
+ Py_DECREF(ret);
+ return ret;
+}
+
+PyObject *
+PyMethod_Self(PyObject *im)
+{
+ PyObject *ret = PyObject_GetAttrString(im, "__self__");
+
+ // We have to return a borrowed reference.
+ // If we don't obey that here, then we get a test error!
+ Py_DECREF(ret);
+ return ret;
+}
+
+/*****************************************************************************
+ *
+ * Support for funcobject.h
+ *
+ */
+
+PyObject *
+PepFunction_Get(PyObject *ob, const char *name)
+{
+ PyObject *ret;
+
+ // We have to return a borrowed reference.
+ ret = PyObject_GetAttrString(ob, name);
+ Py_XDECREF(ret);
+ return ret;
+}
+
+/*****************************************************************************
+ *
+ * Support for funcobject.h
+ *
+ */
+
+// this became necessary after Windows was activated.
+
+PyTypeObject *PepFunction_TypePtr = NULL;
+
+static PyTypeObject *getFunctionType(void)
+{
+ static const char prog[] =
+ "from types import FunctionType\n";
+ return (PyTypeObject *) PepRun_GetResult(prog, "FunctionType");
+}
+
+/*****************************************************************************
+ *
+ * Extra support for signature.cpp
+ *
+ */
+
+PyTypeObject *PepStaticMethod_TypePtr = NULL;
+
+static PyTypeObject *getStaticMethodType(void)
+{
+ static const char prog[] =
+ "StaticMethodType = type(str.__dict__['maketrans'])\n";
+ return (PyTypeObject *) PepRun_GetResult(prog, "StaticMethodType");
+}
+
+#endif // Py_LIMITED_API
+
+/*****************************************************************************
+ *
+ * Common newly needed functions
+ *
+ */
+
+// The introduction of heaptypes converted many type names to the
+// dotted form, since PyType_FromSpec uses it to compute the module
+// name. This function reverts this effect.
+const char *
+PepType_GetNameStr(PyTypeObject *type)
+{
+ const char *ret = PepType(type)->tp_name;
+ const char *nodots = strrchr(ret, '.');
+ if (nodots)
+ ret = nodots + 1;
+ return ret;
+}
+
+/*****************************************************************************
+ *
+ * Module Initialization
+ *
+ */
+
+void
+Pep_Init()
+{
+ check_PepTypeObject_valid();
+#ifdef Py_LIMITED_API
+ Pep_GetVerboseFlag();
+ PepMethod_TypePtr = getMethodType();
+ PepFunction_TypePtr = getFunctionType();
+ PepStaticMethod_TypePtr = getStaticMethodType();
+#endif
+}
+
+} // extern "C"
diff --git a/sources/shiboken2/libshiboken/pep384impl.h b/sources/shiboken2/libshiboken/pep384impl.h
new file mode 100644
index 00000000..fc0e3b40
--- /dev/null
+++ b/sources/shiboken2/libshiboken/pep384impl.h
@@ -0,0 +1,571 @@
+/****************************************************************************
+**
+** Copyright (C) 2018 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of Qt for Python.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 3 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL3 included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 3 requirements
+** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 2.0 or (at your option) the GNU General
+** Public license version 3 or any later version approved by the KDE Free
+** Qt Foundation. The licenses are as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-2.0.html and
+** https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef PEP384IMPL_H
+#define PEP384IMPL_H
+
+#include "sbkpython.h"
+
+extern "C"
+{
+
+/*****************************************************************************
+ *
+ * RESOLVED: memoryobject.h
+ *
+ */
+
+// Extracted into bufferprocs27.h
+#ifdef Py_LIMITED_API
+#include "bufferprocs27.h"
+#endif
+
+/*****************************************************************************
+ *
+ * RESOLVED: object.h
+ *
+ */
+#ifdef Py_LIMITED_API
+// Why the hell is this useful debugging function not allowed?
+LIBSHIBOKEN_API void _PyObject_Dump(PyObject *);
+#endif
+
+/*
+ * There are a few structures that are needed, but cannot be used without
+ * breaking the API. We use some heuristics to get those fields anyway
+ * and validate that we really found them, see Pepresolve.cpp .
+ */
+
+// PepType is just a typecast that allows direct access. This is
+// often better to read than the reversal via the former macro
+// functions PepType_tp_xxx.
+#define PepType(o) (reinterpret_cast<PepTypeObject*>(o))
+
+#ifdef Py_LIMITED_API
+
+/*
+ * These are the type object fields that we use.
+ * We will verify that they never change.
+ * The unused fields are intentionally named as "void *Xnn" because
+ * the chance is smaller to forget to validate a field.
+ * When we need more fields, we replace it back and add it to the
+ * validation.
+ */
+typedef struct _peptypeobject {
+ PyVarObject ob_base;
+ const char *tp_name;
+ Py_ssize_t tp_basicsize;
+ void *X03; // Py_ssize_t tp_itemsize;
+ void *X04; // destructor tp_dealloc;
+ void *X05; // printfunc tp_print;
+ void *X06; // getattrfunc tp_getattr;
+ void *X07; // setattrfunc tp_setattr;
+ void *X08; // PyAsyncMethods *tp_as_async;
+ void *X09; // reprfunc tp_repr;
+ void *X10; // PyNumberMethods *tp_as_number;
+ void *X11; // PySequenceMethods *tp_as_sequence;
+ void *X12; // PyMappingMethods *tp_as_mapping;
+ void *X13; // hashfunc tp_hash;
+ ternaryfunc tp_call;
+ reprfunc tp_str;
+ void *X16; // getattrofunc tp_getattro;
+ void *X17; // setattrofunc tp_setattro;
+ void *X18; // PyBufferProcs *tp_as_buffer;
+ void *X19; // unsigned long tp_flags;
+ void *X20; // const char *tp_doc;
+ traverseproc tp_traverse;
+ inquiry tp_clear;
+ void *X23; // richcmpfunc tp_richcompare;
+ Py_ssize_t tp_weaklistoffset;
+ void *X25; // getiterfunc tp_iter;
+ void *X26; // iternextfunc tp_iternext;
+ struct PyMethodDef *tp_methods;
+ void *X28; // struct PyMemberDef *tp_members;
+ void *X29; // struct PyGetSetDef *tp_getset;
+ struct _typeobject *tp_base;
+ PyObject *tp_dict;
+ descrgetfunc tp_descr_get;
+ void *X33; // descrsetfunc tp_descr_set;
+ Py_ssize_t tp_dictoffset;
+ initproc tp_init;
+ allocfunc tp_alloc;
+ newfunc tp_new;
+ freefunc tp_free;
+ inquiry tp_is_gc; /* For PyObject_IS_GC */
+ PyObject *tp_bases;
+ PyObject *tp_mro; /* method resolution order */
+
+} PepTypeObject;
+
+LIBSHIBOKEN_API unaryfunc PepType_nb_index(PyTypeObject *type);
+
+#undef PyIndex_Check
+
+LIBSHIBOKEN_API int PyIndex_Check(PyObject *obj);
+
+#undef PyObject_IS_GC
+#define PyObject_IS_GC(o) (PyType_IS_GC(Py_TYPE(o)) && \
+ ( PepType(Py_TYPE(o))->tp_is_gc == NULL || \
+ PepType(Py_TYPE(o))->tp_is_gc(o) ))
+
+#else
+#define PepTypeObject PyTypeObject
+#define PepType_nb_index(o) (PepType(o)->nb_index)
+#endif // Py_LIMITED_API
+
+struct SbkObjectTypePrivate;
+struct PySideQFlagsTypePrivate;
+struct _SbkGenericTypePrivate;
+
+#define PepHeapType_SIZE \
+ (reinterpret_cast<PepTypeObject*>(&PyType_Type)->tp_basicsize)
+
+#define _genericTypeExtender(etype) \
+ (reinterpret_cast<char*>(etype) + PepHeapType_SIZE)
+
+#define PepType_SOTP(etype) \
+ (*reinterpret_cast<SbkObjectTypePrivate**>(_genericTypeExtender(etype)))
+
+#define PepType_SETP(etype) \
+ (reinterpret_cast<SbkEnumTypePrivate*>(_genericTypeExtender(etype)))
+
+#define PepType_PFTP(etype) \
+ (reinterpret_cast<PySideQFlagsTypePrivate*>(_genericTypeExtender(etype)))
+
+#define PepType_SGTP(etype) \
+ (reinterpret_cast<_SbkGenericTypePrivate*>(_genericTypeExtender(etype)))
+
+// functions used everywhere
+LIBSHIBOKEN_API const char *PepType_GetNameStr(PyTypeObject *type);
+
+/*****************************************************************************
+ *
+ * RESOLVED: longobject.h
+ *
+ */
+#ifdef Py_LIMITED_API
+LIBSHIBOKEN_API int _PepLong_AsInt(PyObject *);
+#else
+#define _PepLong_AsInt _PyLong_AsInt
+#endif
+
+/*****************************************************************************
+ *
+ * RESOLVED: pydebug.h
+ *
+ */
+#ifdef Py_LIMITED_API
+/*
+ * We have no direct access to Py_VerboseFlag because debugging is not
+ * supported. The python developers are partially a bit too rigorous.
+ * Instead, we compute the value and use a function call macro.
+ * Was before: extern LIBSHIBOKEN_API int Py_VerboseFlag;
+ */
+LIBSHIBOKEN_API int Pep_GetFlag(const char *name);
+LIBSHIBOKEN_API int Pep_GetVerboseFlag(void);
+#define Py_VerboseFlag Pep_GetVerboseFlag()
+#endif
+
+/*****************************************************************************
+ *
+ * RESOLVED: unicodeobject.h
+ *
+ */
+#ifdef Py_LIMITED_API
+
+LIBSHIBOKEN_API char *_PepUnicode_AsString(PyObject *);
+
+#define PyUnicode_GET_SIZE(op) PyUnicode_GetSize((PyObject *)(op))
+
+#else
+#define _PepUnicode_AsString PyUnicode_AsUTF8
+#endif
+
+/*****************************************************************************
+ *
+ * RESOLVED: bytesobject.h
+ *
+ */
+#ifdef Py_LIMITED_API
+#define PyBytes_AS_STRING(op) PyBytes_AsString(op)
+#define PyBytes_GET_SIZE(op) PyBytes_Size(op)
+#endif
+
+/*****************************************************************************
+ *
+ * RESOLVED: floatobject.h
+ *
+ */
+#ifdef Py_LIMITED_API
+#define PyFloat_AS_DOUBLE(op) PyFloat_AsDouble(op)
+#endif
+
+/*****************************************************************************
+ *
+ * RESOLVED: tupleobject.h
+ *
+ */
+#ifdef Py_LIMITED_API
+#define PyTuple_GET_ITEM(op, i) PyTuple_GetItem((PyObject *)op, i)
+#define PyTuple_GET_SIZE(op) PyTuple_Size((PyObject *)op)
+#define PyTuple_SET_ITEM(op, i, v) PyTuple_SetItem(op, i, v)
+#endif
+
+/*****************************************************************************
+ *
+ * RESOLVED: listobject.h
+ *
+ */
+#ifdef Py_LIMITED_API
+#define PyList_GET_ITEM(op, i) PyList_GetItem(op, i)
+#define PyList_SET_ITEM(op, i, v) PyList_SetItem(op, i, v)
+#define PyList_GET_SIZE(op) PyList_Size(op)
+#endif
+
+/*****************************************************************************
+ *
+ * RESOLVED: methodobject.h
+ *
+ */
+
+#ifdef Py_LIMITED_API
+
+typedef struct _pycfunc PyCFunctionObject;
+#define PyCFunction_GET_FUNCTION(func) PyCFunction_GetFunction((PyObject *)func)
+#define PyCFunction_GET_SELF(func) PyCFunction_GetSelf((PyObject *)func)
+#define PyCFunction_GET_FLAGS(func) PyCFunction_GetFlags((PyObject *)func)
+#define PepCFunction_GET_NAMESTR(func) \
+ _PepUnicode_AsString(PyObject_GetAttrString((PyObject *)func, "__name__"))
+#else
+#define PepCFunction_GET_NAMESTR(func) ((func)->m_ml->ml_name)
+#endif
+
+/*****************************************************************************
+ *
+ * RESOLVED: descrobject.h
+ *
+ */
+#ifdef Py_LIMITED_API
+typedef struct _methoddescr PyMethodDescrObject;
+#endif
+
+/*****************************************************************************
+ *
+ * RESOLVED: pystate.h
+ *
+ */
+
+/*
+ * pystate provides the data structure that is needed for the trashcan
+ * algorithm. Unfortunately, it is not included in the limited API.
+ * We have two options:
+ *
+ * (1) ignore trashcan and live without secured deeply nested structures,
+ * (2) maintain the structure ourselves and make sure it does not change.
+ *
+ * I have chosen the second option.
+ *
+ * When a new python version appears, you need to check compatibility of
+ * the PyThreadState structure (pystate.h) and the trashcan macros at the
+ * end of object.h .
+ */
+
+#ifdef Py_LIMITED_API
+
+#define Py_TRASH_MIN_COMPATIBLE 0x03020400
+#define Py_TRASH_MAX_COMPATIBLE 0x030700A0
+
+#if PY_VERSION_HEX >= Py_TRASH_MIN_COMPATIBLE && \
+ PY_VERSION_HEX <= Py_TRASH_MAX_COMPATIBLE
+typedef int (*Py_tracefunc)(PyObject *, struct _frame *, int, PyObject *);
+
+// This structure has the trashcan variables since Python 3.2.4.
+// We renamed all but the trashcan fields to make sure that we don't use
+// anything else somewhere.
+
+typedef struct _ts {
+ struct _ts *Pep_prev;
+ struct _ts *Pep_next;
+ PyInterpreterState *Pep_interp;
+
+ struct _frame *Pep_frame;
+ int Pep_recursion_depth;
+ char Pep_overflowed;
+ char Pep_recursion_critical;
+
+ int Pep_tracing;
+ int Pep_use_tracing;
+
+ Py_tracefunc Pep_c_profilefunc;
+ Py_tracefunc Pep_c_tracefunc;
+ PyObject *Pep_c_profileobj;
+ PyObject *Pep_c_traceobj;
+
+ PyObject *Pep_curexc_type;
+ PyObject *Pep_curexc_value;
+ PyObject *Pep_curexc_traceback;
+
+ PyObject *Pep_exc_type;
+ PyObject *Pep_exc_value;
+ PyObject *Pep_exc_traceback;
+
+ PyObject *Pep_dict;
+
+ int Pep_gilstate_counter;
+
+ PyObject *Pep_async_exc;
+ long Pep_thread_id;
+ // These two variables only are of interest to us.
+ int trash_delete_nesting;
+ PyObject *trash_delete_later;
+ // Here we cut away the rest of the reduced structure.
+} PyThreadState;
+#else
+#error *** Please check compatibility of the trashcan code, see Pep.h ***
+#endif
+
+#endif // Py_LIMITED_API
+
+/*****************************************************************************
+ *
+ * RESOLVED: pythonrun.h
+ *
+ */
+#ifdef Py_LIMITED_API
+LIBSHIBOKEN_API PyObject *PyRun_String(const char *, int, PyObject *, PyObject *);
+#endif
+
+/*****************************************************************************
+ *
+ * RESOLVED: abstract.h
+ *
+ */
+#ifdef Py_LIMITED_API
+
+// This definition breaks the limited API a little, because it re-enables the
+// buffer functions.
+// But this is no problem as we check it's validity for every version.
+
+#define PYTHON_BUFFER_VERSION_COMPATIBLE (PY_VERSION_HEX >= 0x03030000 && \
+ PY_VERSION_HEX < 0X0306FFFF)
+#if !PYTHON_BUFFER_VERSION_COMPATIBLE
+# error Please check the buffer compatibility for this python version!
+#endif
+
+typedef struct {
+ getbufferproc bf_getbuffer;
+ releasebufferproc bf_releasebuffer;
+} PyBufferProcs;
+
+typedef struct _Pepbuffertype {
+ PyVarObject ob_base;
+ void *skip[17];
+ PyBufferProcs *tp_as_buffer;
+} PepBufferType;
+
+#define PepType_AS_BUFFER(type) \
+ reinterpret_cast<PepBufferType *>(type)->tp_as_buffer
+
+#define PyObject_CheckBuffer(obj) \
+ ((PepType_AS_BUFFER(Py_TYPE(obj)) != NULL) && \
+ (PepType_AS_BUFFER(Py_TYPE(obj))->bf_getbuffer != NULL))
+
+LIBSHIBOKEN_API int PyObject_GetBuffer(PyObject *ob, Pep_buffer *view, int flags);
+LIBSHIBOKEN_API void PyBuffer_Release(Pep_buffer *view);
+
+#else
+
+#define Pep_buffer Py_buffer
+
+#endif /* Py_LIMITED_API */
+
+/*****************************************************************************
+ *
+ * RESOLVED: funcobject.h
+ *
+ */
+#ifdef Py_LIMITED_API
+typedef struct _func PyFunctionObject;
+
+extern LIBSHIBOKEN_API PyTypeObject *PepFunction_TypePtr;
+LIBSHIBOKEN_API PyObject *PepFunction_Get(PyObject *, const char *);
+
+#define PyFunction_Check(op) (Py_TYPE(op) == PepFunction_TypePtr)
+#define PyFunction_GET_CODE(func) PyFunction_GetCode(func)
+
+#define PyFunction_GetCode(func) PepFunction_Get((PyObject *)func, "__code__")
+#define PepFunction_GetName(func) PepFunction_Get((PyObject *)func, "__name__")
+#else
+#define PepFunction_GetName(func) (((PyFunctionObject *)func)->func_name)
+#endif
+
+/*****************************************************************************
+ *
+ * RESOLVED: classobject.h
+ *
+ */
+#ifdef Py_LIMITED_API
+
+typedef struct _meth PyMethodObject;
+
+extern LIBSHIBOKEN_API PyTypeObject *PepMethod_TypePtr;
+
+LIBSHIBOKEN_API PyObject *PyMethod_New(PyObject *, PyObject *);
+LIBSHIBOKEN_API PyObject *PyMethod_Function(PyObject *);
+LIBSHIBOKEN_API PyObject *PyMethod_Self(PyObject *);
+
+#define PyMethod_Check(op) ((op)->ob_type == PepMethod_TypePtr)
+
+#define PyMethod_GET_SELF(op) PyMethod_Self(op)
+#define PyMethod_GET_FUNCTION(op) PyMethod_Function(op)
+#endif
+
+/*****************************************************************************
+ *
+ * RESOLVED: code.h
+ *
+ */
+#ifdef Py_LIMITED_API
+/* Bytecode object */
+ // we have to grab the code object from python
+typedef struct _code PyCodeObject;
+
+LIBSHIBOKEN_API int PepCode_Get(PyCodeObject *co, const char *name);
+
+#define PepCode_GET_FLAGS(o) PepCode_Get(o, "co_flags")
+#define PepCode_GET_ARGCOUNT(o) PepCode_Get(o, "co_argcount")
+
+/* Masks for co_flags above */
+#define CO_OPTIMIZED 0x0001
+#define CO_NEWLOCALS 0x0002
+#define CO_VARARGS 0x0004
+#define CO_VARKEYWORDS 0x0008
+#define CO_NESTED 0x0010
+#define CO_GENERATOR 0x0020
+#else
+#define PepCode_GET_FLAGS(o) ((o)->co_flags)
+#define PepCode_GET_ARGCOUNT(o) ((o)->co_argcount)
+#endif
+
+/*****************************************************************************
+ *
+ * RESOLVED: datetime.h
+ *
+ */
+#ifdef Py_LIMITED_API
+
+LIBSHIBOKEN_API int PyDateTime_Get(PyObject *ob, const char *name);
+
+#define PyDateTime_GetYear(o) PyDateTime_Get(o, "year")
+#define PyDateTime_GetMonth(o) PyDateTime_Get(o, "month")
+#define PyDateTime_GetDay(o) PyDateTime_Get(o, "day")
+#define PyDateTime_GetHour(o) PyDateTime_Get(o, "hour")
+#define PyDateTime_GetMinute(o) PyDateTime_Get(o, "minute")
+#define PyDateTime_GetSecond(o) PyDateTime_Get(o, "second")
+#define PyDateTime_GetMicrosecond(o) PyDateTime_Get(o, "microsecond")
+#define PyDateTime_GetFold(o) PyDateTime_Get(o, "fold")
+
+#define PyDateTime_GET_YEAR(o) PyDateTime_GetYear(o)
+#define PyDateTime_GET_MONTH(o) PyDateTime_GetMonth(o)
+#define PyDateTime_GET_DAY(o) PyDateTime_GetDay(o)
+
+#define PyDateTime_DATE_GET_HOUR(o) PyDateTime_GetHour(o)
+#define PyDateTime_DATE_GET_MINUTE(o) PyDateTime_GetMinute(o)
+#define PyDateTime_DATE_GET_SECOND(o) PyDateTime_GetSecond(o)
+#define PyDateTime_DATE_GET_MICROSECOND(o) PyDateTime_GetMicrosecond(o)
+#define PyDateTime_DATE_GET_FOLD(o) PyDateTime_GetFold(o)
+
+#define PyDateTime_TIME_GET_HOUR(o) PyDateTime_GetHour(o)
+#define PyDateTime_TIME_GET_MINUTE(o) PyDateTime_GetMinute(o)
+#define PyDateTime_TIME_GET_SECOND(o) PyDateTime_GetSecond(o)
+#define PyDateTime_TIME_GET_MICROSECOND(o) PyDateTime_GetMicrosecond(o)
+#define PyDateTime_TIME_GET_FOLD(o) PyDateTime_GetFold(o)
+
+/* Define structure slightly similar to C API. */
+typedef struct {
+ PyObject *module;
+ /* type objects */
+ PyTypeObject *DateType;
+ PyTypeObject *DateTimeType;
+ PyTypeObject *TimeType;
+ PyTypeObject *DeltaType;
+ PyTypeObject *TZInfoType;
+} datetime_struc;
+
+LIBSHIBOKEN_API datetime_struc *init_DateTime(void);
+
+#define PyDateTime_IMPORT PyDateTimeAPI = init_DateTime()
+
+extern LIBSHIBOKEN_API datetime_struc *PyDateTimeAPI;
+
+#define PyDate_Check(op) PyObject_TypeCheck(op, PyDateTimeAPI->DateType)
+#define PyDateTime_Check(op) PyObject_TypeCheck(op, PyDateTimeAPI->DateTimeType)
+#define PyTime_Check(op) PyObject_TypeCheck(op, PyDateTimeAPI->TimeType)
+
+LIBSHIBOKEN_API PyObject *PyDate_FromDate(int year, int month, int day);
+LIBSHIBOKEN_API PyObject *PyDateTime_FromDateAndTime(
+ int year, int month, int day, int hour, int min, int sec, int usec);
+LIBSHIBOKEN_API PyObject *PyTime_FromTime(
+ int hour, int minute, int second, int usecond);
+
+#endif /* Py_LIMITED_API */
+
+/*****************************************************************************
+ *
+ * Extra support for signature.cpp
+ *
+ */
+
+#ifdef Py_LIMITED_API
+extern LIBSHIBOKEN_API PyTypeObject *PepStaticMethod_TypePtr;
+#else
+#define PepStaticMethod_TypePtr &PyStaticMethod_Type
+#endif
+
+/*****************************************************************************
+ *
+ * Module Initialization
+ *
+ */
+
+LIBSHIBOKEN_API void Pep_Init(void);
+
+} // extern "C"
+
+#endif // PEP384IMPL_H
diff --git a/sources/shiboken2/libshiboken/python25compat.h b/sources/shiboken2/libshiboken/python25compat.h
index 42f78481..fc25aa3e 100644
--- a/sources/shiboken2/libshiboken/python25compat.h
+++ b/sources/shiboken2/libshiboken/python25compat.h
@@ -39,7 +39,7 @@
#ifndef PYTHON25COMPAT_H
#define PYTHON25COMPAT_H
-#include <Python.h>
+#include "sbkpython.h"
#include <cstring>
/*
diff --git a/sources/shiboken2/libshiboken/qapp_macro.cpp b/sources/shiboken2/libshiboken/qapp_macro.cpp
index e6a877a3..f69d0f93 100644
--- a/sources/shiboken2/libshiboken/qapp_macro.cpp
+++ b/sources/shiboken2/libshiboken/qapp_macro.cpp
@@ -119,8 +119,8 @@ MakeSingletonQAppWrapper(PyTypeObject *type)
if (type == NULL)
type = Py_NONE_TYPE;
if (!(type == Py_NONE_TYPE || Py_TYPE(qApp_content) == Py_NONE_TYPE)) {
- const char *res_name = strrchr(Py_TYPE(qApp_content)->tp_name, '.')+1;
- const char *type_name = strrchr(type->tp_name, '.')+1;
+ const char *res_name = PepType_GetNameStr(Py_TYPE(qApp_content));
+ const char *type_name = PepType_GetNameStr(type);
PyErr_Format(PyExc_RuntimeError, "Please destroy the %s singleton before"
" creating a new %s instance.", res_name, type_name);
return NULL;
diff --git a/sources/shiboken2/libshiboken/qt_attribution.json b/sources/shiboken2/libshiboken/qt_attribution.json
new file mode 100644
index 00000000..a90cc604
--- /dev/null
+++ b/sources/shiboken2/libshiboken/qt_attribution.json
@@ -0,0 +1,12 @@
+{
+ "Id": "python",
+ "Name": "Python",
+ "QDocModule": "QtForPython",
+ "QtUsage": "Used for Qt for Python in the signature extension.",
+ "Description": "Qt for Python is an add-on for Python. The libshiboken packages of PySide uses certain parts of the source files (typespec.cpp, typespec.h, bufferprocs27.cpp, bufferprocs27.h). See the folder sources/shiboken2/libshiboken .",
+ "Homepage": "http://www.python.org/",
+ "Version": "3.6.5",
+ "License": "PSF LICENSE AGREEMENT FOR PYTHON 3.6.5",
+ "LicenseFile": "bufferprocs27.h",
+ "Copyright": "© Copyright 2001-2018, Python Software Foundation."
+}
diff --git a/sources/shiboken2/libshiboken/sbkarrayconverter.cpp b/sources/shiboken2/libshiboken/sbkarrayconverter.cpp
index 1646c911..58e0b18a 100644
--- a/sources/shiboken2/libshiboken/sbkarrayconverter.cpp
+++ b/sources/shiboken2/libshiboken/sbkarrayconverter.cpp
@@ -162,7 +162,7 @@ static void sequenceToCppIntArray(PyObject *pyIn, void *cppOut)
{
ArrayHandle<int> *handle = reinterpret_cast<ArrayHandle<int> *>(cppOut);
handle->allocate(PySequence_Size(pyIn));
- convertPySequence(pyIn, _PyLong_AsInt, handle->data());
+ convertPySequence(pyIn, _PepLong_AsInt, handle->data());
}
static PythonToCppFunc sequenceToCppIntArrayCheck(PyObject *pyIn, int dim1, int /* dim2 */)
diff --git a/sources/shiboken2/libshiboken/sbkconverter.cpp b/sources/shiboken2/libshiboken/sbkconverter.cpp
index 64884d60..d4d3ac89 100644
--- a/sources/shiboken2/libshiboken/sbkconverter.cpp
+++ b/sources/shiboken2/libshiboken/sbkconverter.cpp
@@ -112,6 +112,8 @@ SbkConverter *createConverterObject(PyTypeObject *type,
{
SbkConverter* converter = new SbkConverter;
converter->pythonType = type;
+ // PYSIDE-595: All types are heaptypes now, so provide reference.
+ Py_XINCREF(type);
converter->pointerToPython = pointerToPythonFunc;
converter->copyToPython = copyToPythonFunc;
@@ -133,7 +135,7 @@ SbkConverter* createConverter(SbkObjectType* type,
createConverterObject(reinterpret_cast<PyTypeObject *>(type),
toCppPointerConvFunc, toCppPointerCheckFunc,
pointerToPythonFunc, copyToPythonFunc);
- type->d->converter = converter;
+ PepType_SOTP(type)->converter = converter;
return converter;
}
@@ -172,12 +174,12 @@ void addPythonToCppValueConversion(SbkObjectType* type,
PythonToCppFunc pythonToCppFunc,
IsConvertibleToCppFunc isConvertibleToCppFunc)
{
- addPythonToCppValueConversion(type->d->converter, pythonToCppFunc, isConvertibleToCppFunc);
+ addPythonToCppValueConversion(PepType_SOTP(type)->converter, pythonToCppFunc, isConvertibleToCppFunc);
}
-PyObject* pointerToPython(const SbkObjectType *type, const void *cppIn)
+PyObject* pointerToPython(SbkObjectType *type, const void *cppIn)
{
- return pointerToPython(type->d->converter, cppIn);
+ return pointerToPython(PepType_SOTP(type)->converter, cppIn);
}
PyObject* pointerToPython(const SbkConverter *converter, const void *cppIn)
@@ -187,15 +189,15 @@ PyObject* pointerToPython(const SbkConverter *converter, const void *cppIn)
Py_RETURN_NONE;
if (!converter->pointerToPython) {
warning(PyExc_RuntimeWarning, 0, "pointerToPython(): SbkConverter::pointerToPython is null for \"%s\".",
- converter->pythonType->tp_name);
+ PepType(converter->pythonType)->tp_name);
Py_RETURN_NONE;
}
return converter->pointerToPython(cppIn);
}
-PyObject* referenceToPython(const SbkObjectType *type, const void *cppIn)
+PyObject* referenceToPython(SbkObjectType *type, const void *cppIn)
{
- return referenceToPython(type->d->converter, cppIn);
+ return referenceToPython(PepType_SOTP(type)->converter, cppIn);
}
PyObject* referenceToPython(const SbkConverter *converter, const void *cppIn)
@@ -209,7 +211,7 @@ PyObject* referenceToPython(const SbkConverter *converter, const void *cppIn)
}
if (!converter->pointerToPython) {
warning(PyExc_RuntimeWarning, 0, "referenceToPython(): SbkConverter::pointerToPython is null for \"%s\".",
- converter->pythonType->tp_name);
+ PepType(converter->pythonType)->tp_name);
Py_RETURN_NONE;
}
return converter->pointerToPython(cppIn);
@@ -221,24 +223,24 @@ static inline PyObject* CopyCppToPython(const SbkConverter *converter, const voi
Py_RETURN_NONE;
if (!converter->copyToPython) {
warning(PyExc_RuntimeWarning, 0, "CopyCppToPython(): SbkConverter::copyToPython is null for \"%s\".",
- converter->pythonType->tp_name);
+ PepType(converter->pythonType)->tp_name);
Py_RETURN_NONE;
}
return converter->copyToPython(cppIn);
}
-PyObject* copyToPython(const SbkObjectType *type, const void *cppIn)
+PyObject* copyToPython(SbkObjectType *type, const void *cppIn)
{
- return CopyCppToPython(type->d->converter, cppIn);
+ return CopyCppToPython(PepType_SOTP(type)->converter, cppIn);
}
PyObject* copyToPython(const SbkConverter *converter, const void *cppIn)
{
return CopyCppToPython(converter, cppIn);
}
-PythonToCppFunc isPythonToCppPointerConvertible(const SbkObjectType *type, PyObject *pyIn)
+PythonToCppFunc isPythonToCppPointerConvertible(SbkObjectType *type, PyObject *pyIn)
{
assert(pyIn);
- return type->d->converter->toCppPointerConversion.first(pyIn);
+ return PepType_SOTP(type)->converter->toCppPointerConversion.first(pyIn);
}
static inline PythonToCppFunc IsPythonToCppConvertible(const SbkConverter *converter, PyObject *pyIn)
@@ -252,9 +254,9 @@ static inline PythonToCppFunc IsPythonToCppConvertible(const SbkConverter *conve
}
return 0;
}
-PythonToCppFunc isPythonToCppValueConvertible(const SbkObjectType *type, PyObject *pyIn)
+PythonToCppFunc isPythonToCppValueConvertible(SbkObjectType *type, PyObject *pyIn)
{
- return IsPythonToCppConvertible(type->d->converter, pyIn);
+ return IsPythonToCppConvertible(PepType_SOTP(type)->converter, pyIn);
}
PythonToCppFunc isPythonToCppConvertible(const SbkConverter *converter, PyObject *pyIn)
{
@@ -272,7 +274,7 @@ PythonToCppFunc isPythonToCppConvertible(const SbkArrayConverter *converter,
return nullptr;
}
-PythonToCppFunc isPythonToCppReferenceConvertible(const SbkObjectType *type, PyObject *pyIn)
+PythonToCppFunc isPythonToCppReferenceConvertible(SbkObjectType *type, PyObject *pyIn)
{
if (pyIn != Py_None) {
PythonToCppFunc toCpp = isPythonToCppPointerConvertible(type, pyIn);
@@ -329,10 +331,10 @@ static void _pythonToCppCopy(const SbkConverter *converter, PyObject *pyIn, void
toCpp(pyIn, cppOut);
}
-void pythonToCppCopy(const SbkObjectType *type, PyObject *pyIn, void *cppOut)
+void pythonToCppCopy(SbkObjectType *type, PyObject *pyIn, void *cppOut)
{
assert(type);
- _pythonToCppCopy(type->d->converter, pyIn, cppOut);
+ _pythonToCppCopy(PepType_SOTP(type)->converter, pyIn, cppOut);
}
void pythonToCppCopy(const SbkConverter *converter, PyObject *pyIn, void *cppOut)
@@ -340,16 +342,16 @@ void pythonToCppCopy(const SbkConverter *converter, PyObject *pyIn, void *cppOut
_pythonToCppCopy(converter, pyIn, cppOut);
}
-bool isImplicitConversion(const SbkObjectType *type, PythonToCppFunc toCppFunc)
+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)
+ if (toCppFunc == PepType_SOTP(type)->converter->toCppPointerConversion.second)
return false;
// Object Types doesn't have any kind of value conversion,
// only C++ pointer retrieval.
- if (type->d->converter->toCppConversions.empty())
+ if (PepType_SOTP(type)->converter->toCppConversions.empty())
return false;
// The first conversion of the non-pointer conversion list is
@@ -359,7 +361,7 @@ bool isImplicitConversion(const SbkObjectType *type, PythonToCppFunc toCppFunc)
// 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();
+ ToCppConversionList::iterator conv = PepType_SOTP(type)->converter->toCppConversions.begin();
return toCppFunc != (*conv).second;
}
@@ -411,10 +413,10 @@ bool convertibleSequenceTypes(const SbkConverter *converter, PyObject *pyIn)
}
return true;
}
-bool convertibleSequenceTypes(const SbkObjectType *type, PyObject *pyIn)
+bool convertibleSequenceTypes(SbkObjectType *type, PyObject *pyIn)
{
assert(type);
- return convertibleSequenceTypes(type->d->converter, pyIn);
+ return convertibleSequenceTypes(PepType_SOTP(type)->converter, pyIn);
}
bool checkPairTypes(PyTypeObject* firstType, PyTypeObject* secondType, PyObject* pyIn)
diff --git a/sources/shiboken2/libshiboken/sbkconverter.h b/sources/shiboken2/libshiboken/sbkconverter.h
index da71db5b..0effebf5 100644
--- a/sources/shiboken2/libshiboken/sbkconverter.h
+++ b/sources/shiboken2/libshiboken/sbkconverter.h
@@ -191,7 +191,7 @@ LIBSHIBOKEN_API void addPythonToCppValueConversion(SbkObjectType* type,
* TYPE* var;
* PyObject* pyVar = pointerToPython(SBKTYPE, &var);
*/
-LIBSHIBOKEN_API PyObject* pointerToPython(const SbkObjectType *type, const void *cppIn);
+LIBSHIBOKEN_API PyObject* pointerToPython(SbkObjectType *type, const void *cppIn);
LIBSHIBOKEN_API PyObject* pointerToPython(const SbkConverter *converter, const void *cppIn);
/**
@@ -203,7 +203,7 @@ LIBSHIBOKEN_API PyObject* pointerToPython(const SbkConverter *converter, const v
* TYPE& var = SOMETHING;
* PyObject* pyVar = referenceToPython(SBKTYPE, &var);
*/
-LIBSHIBOKEN_API PyObject* referenceToPython(const SbkObjectType *type, const void *cppIn);
+LIBSHIBOKEN_API PyObject* referenceToPython(SbkObjectType *type, const void *cppIn);
LIBSHIBOKEN_API PyObject* referenceToPython(const SbkConverter *converter, const void *cppIn);
/**
@@ -213,7 +213,7 @@ LIBSHIBOKEN_API PyObject* referenceToPython(const SbkConverter *converter, const
* TYPE var;
* PyObject* pyVar = copyToPython(SBKTYPE, &var);
*/
-LIBSHIBOKEN_API PyObject* copyToPython(const SbkObjectType *type, const void *cppIn);
+LIBSHIBOKEN_API PyObject* copyToPython(SbkObjectType *type, const void *cppIn);
LIBSHIBOKEN_API PyObject* copyToPython(const SbkConverter *converter, const void *cppIn);
// Python -> C++ ---------------------------------------------------------------------------
@@ -222,7 +222,7 @@ LIBSHIBOKEN_API PyObject* copyToPython(const SbkConverter *converter, const void
* 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);
+LIBSHIBOKEN_API PythonToCppFunc isPythonToCppPointerConvertible(SbkObjectType *type, PyObject *pyIn);
/**
* Returns a Python to C++ conversion function if the Python object is convertible to a C++ value.
@@ -230,7 +230,7 @@ LIBSHIBOKEN_API PythonToCppFunc isPythonToCppPointerConvertible(const SbkObjectT
* 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);
+LIBSHIBOKEN_API PythonToCppFunc isPythonToCppValueConvertible(SbkObjectType *type, PyObject *pyIn);
/**
* Returns a Python to C++ conversion function if the Python object is convertible to a C++ reference.
@@ -238,7 +238,7 @@ LIBSHIBOKEN_API PythonToCppFunc isPythonToCppValueConvertible(const SbkObjectTyp
* 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);
+LIBSHIBOKEN_API PythonToCppFunc isPythonToCppReferenceConvertible(SbkObjectType *type, PyObject *pyIn);
/// This is the same as isPythonToCppValueConvertible function.
LIBSHIBOKEN_API PythonToCppFunc isPythonToCppConvertible(const SbkConverter *converter, PyObject *pyIn);
@@ -257,7 +257,7 @@ LIBSHIBOKEN_API void pythonToCppPointer(SbkObjectType* type, PyObject* pyIn, voi
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(SbkObjectType *type, PyObject *pyIn, void *cppOut);
LIBSHIBOKEN_API void pythonToCppCopy(const SbkConverter *converter, PyObject *pyIn, void *cppOut);
/**
@@ -271,7 +271,7 @@ LIBSHIBOKEN_API void nonePythonToCppNullPtr(PyObject*, void* cppOut);
* 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);
+LIBSHIBOKEN_API bool isImplicitConversion(SbkObjectType *type, PythonToCppFunc toCpp);
/// Registers a converter with a type name that may be used to retrieve the converter.
LIBSHIBOKEN_API void registerConverterName(SbkConverter* converter, const char* typeName);
@@ -289,7 +289,7 @@ LIBSHIBOKEN_API bool checkSequenceTypes(PyTypeObject* type, PyObject* pyIn);
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);
+LIBSHIBOKEN_API bool convertibleSequenceTypes(SbkObjectType *type, PyObject *pyIn);
/// Returns true if a Python sequence can be converted to a C++ pair.
LIBSHIBOKEN_API bool checkPairTypes(PyTypeObject* firstType, PyTypeObject* secondType, PyObject* pyIn);
@@ -394,8 +394,9 @@ template<> inline PyTypeObject* SbkType<unsigned short>() { return &PyInt_Type;
#define PyObject_Check(X) true
#define SbkChar_Check(X) (SbkNumber_Check(X) || Shiboken::String::checkChar(X))
-struct _SbkGenericType { PyHeapTypeObject super; SbkConverter** converter; };
-#define SBK_CONVERTER(pyType) (*reinterpret_cast<_SbkGenericType*>(pyType)->converter)
+struct _SbkGenericTypePrivate {
+ SbkConverter** converter;
+};
#endif // SBK_CONVERTER_H
diff --git a/sources/shiboken2/libshiboken/sbkenum.cpp b/sources/shiboken2/libshiboken/sbkenum.cpp
index 37649f6f..5f753293 100644
--- a/sources/shiboken2/libshiboken/sbkenum.cpp
+++ b/sources/shiboken2/libshiboken/sbkenum.cpp
@@ -1,6 +1,6 @@
/****************************************************************************
**
-** Copyright (C) 2016 The Qt Company Ltd.
+** Copyright (C) 2018 The Qt Company Ltd.
** Contact: https://www.qt.io/licensing/
**
** This file is part of Qt for Python.
@@ -54,14 +54,18 @@
extern "C"
{
-struct SbkEnumType
+struct SbkEnumTypePrivate
{
- PyHeapTypeObject super;
SbkConverter** converterPtr;
SbkConverter* converter;
const char* cppName;
};
+struct SbkEnumType
+{
+ PepTypeObject type;
+};
+
struct SbkEnumObject
{
PyObject_HEAD
@@ -73,21 +77,9 @@ 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));
+ return Shiboken::String::fromFormat("%s.%s", PepType((Py_TYPE(self)))->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;
+ return Shiboken::String::fromFormat("%s(%ld)", PepType((Py_TYPE(self)))->tp_name, enumObj->ob_value);
}
static PyObject* SbkEnumObject_name(PyObject* self, void*)
@@ -266,114 +258,54 @@ static PyGetSetDef SbkEnumGetSetList[] = {
{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,
+static void SbkEnumTypeDealloc(PyObject* pyObj);
+static PyObject* SbkEnumTypeTpNew(PyTypeObject* metatype, PyObject* args, PyObject* kwds);
+
+static PyType_Slot SbkEnumType_Type_slots[] = {
+ {Py_tp_dealloc, (void *)SbkEnumTypeDealloc},
+ {Py_nb_add, (void *)enum_add},
+ {Py_nb_subtract, (void *)enum_subtract},
+ {Py_nb_multiply, (void *)enum_multiply},
#ifndef IS_PY3K
- /* nb_coerce */ 0,
+ {Py_nb_divide, (void *)enum_divide},
#endif
- /* nb_int */ enum_int,
+ {Py_nb_positive, (void *)enum_int},
#ifdef IS_PY3K
- /* nb_reserved */ 0,
- /* nb_float */ 0,
+ {Py_nb_bool, (void *)enum_bool},
#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,
+ {Py_nb_nonzero, (void *)enum_bool},
+ {Py_nb_long, (void *)enum_int},
#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
+ {Py_nb_and, (void *)enum_and},
+ {Py_nb_xor, (void *)enum_xor},
+ {Py_nb_or, (void *)enum_or},
+ {Py_nb_int, (void *)enum_int},
+ {Py_nb_index, (void *)enum_int},
+ {Py_tp_base, (void *)&PyType_Type},
+ {Py_tp_alloc, (void *)PyType_GenericAlloc},
+ {Py_tp_new, (void *)SbkEnumTypeTpNew},
+ {Py_tp_free, (void *)PyObject_GC_Del},
+ {0, 0}
+};
+static PyType_Spec SbkEnumType_Type_spec = {
+ "Shiboken.EnumType",
+ 0, // filled in later
+ sizeof(PyMemberDef),
+ Py_TPFLAGS_DEFAULT|Py_TPFLAGS_BASETYPE|Py_TPFLAGS_CHECKTYPES,
+ SbkEnumType_Type_slots,
};
-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
-};
+PyTypeObject *SbkEnumType_TypeF(void)
+{
+ static PyTypeObject *type = nullptr;
+ if (!type) {
+ SbkEnumType_Type_spec.basicsize =
+ PepHeapType_SIZE + sizeof(SbkEnumTypePrivate);
+ type = (PyTypeObject *)PyType_FromSpec(&SbkEnumType_Type_spec);
+ }
+ return type;
+}
void SbkEnumTypeDealloc(PyObject* pyObj)
{
@@ -381,15 +313,16 @@ void SbkEnumTypeDealloc(PyObject* pyObj)
PyObject_GC_UnTrack(pyObj);
Py_TRASHCAN_SAFE_BEGIN(pyObj);
- if (sbkType->converter) {
- Shiboken::Conversions::deleteConverter(sbkType->converter);
+ if (PepType_SETP(sbkType)->converter) {
+ Shiboken::Conversions::deleteConverter(PepType_SETP(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));
+ newfunc type_new = reinterpret_cast<newfunc>(PyType_GetSlot(&PyType_Type, Py_tp_new));
+ SbkEnumType *newType = reinterpret_cast<SbkEnumType*>(type_new(metatype, args, kwds));
if (!newType)
return 0;
return reinterpret_cast<PyObject*>(newType);
@@ -417,14 +350,14 @@ namespace Enum {
bool check(PyObject* pyObj)
{
- return Py_TYPE(pyObj->ob_type) == &SbkEnumType_Type;
+ return Py_TYPE(Py_TYPE(pyObj)) == SbkEnumType_TypeF();
}
PyObject* getEnumItemFromValue(PyTypeObject* enumType, long itemValue)
{
PyObject *key, *value;
Py_ssize_t pos = 0;
- PyObject* values = PyDict_GetItemString(enumType->tp_dict, const_cast<char*>("values"));
+ PyObject *values = PyDict_GetItemString(PepType(enumType)->tp_dict, const_cast<char*>("values"));
while (PyDict_Next(values, &pos, &key, &value)) {
SbkEnumObject *obj = reinterpret_cast<SbkEnumObject *>(value);
@@ -438,9 +371,7 @@ PyObject* getEnumItemFromValue(PyTypeObject* enumType, long itemValue)
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;
+ PyTypeObject* enumType = newTypeWithName(fullName, cppName, flagsType);
if (PyType_Ready(enumType) < 0)
return 0;
return enumType;
@@ -451,7 +382,8 @@ PyTypeObject* createGlobalEnum(PyObject* module, const char* name, const char* f
PyTypeObject* enumType = createEnum(fullName, cppName, name, flagsType);
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)
+ if (flagsType && PyModule_AddObject(module, PepType_GetNameStr(flagsType),
+ reinterpret_cast<PyObject *>(flagsType)) < 0)
return 0;
return enumType;
}
@@ -459,17 +391,20 @@ PyTypeObject* createGlobalEnum(PyObject* module, const char* name, const char* f
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;
+ if (enumType && PyDict_SetItemString(PepType(scope)->tp_dict, name,
+ reinterpret_cast<PyObject *>(enumType)) < 0)
+ return nullptr;
+ if (flagsType && PyDict_SetItemString(PepType(scope)->tp_dict,
+ PepType_GetNameStr(flagsType),
+ reinterpret_cast<PyObject *>(flagsType)) < 0)
+ return nullptr;
return enumType;
}
static PyObject* createEnumItem(PyTypeObject* enumType, const char* itemName, long itemValue)
{
PyObject* enumItem = newItem(enumType, itemValue, itemName);
- if (PyDict_SetItemString(enumType->tp_dict, itemName, enumItem) < 0)
+ if (PyDict_SetItemString(PepType(enumType)->tp_dict, itemName, enumItem) < 0)
return 0;
Py_DECREF(enumItem);
return enumItem;
@@ -496,7 +431,7 @@ bool createScopedEnumItem(PyTypeObject *enumType, PyTypeObject *scope,
const char *itemName, long itemValue)
{
if (PyObject *enumItem = createEnumItem(enumType, itemName, itemValue)) {
- if (PyDict_SetItemString(scope->tp_dict, itemName, enumItem) < 0)
+ if (PyDict_SetItemString(PepType(scope)->tp_dict, itemName, enumItem) < 0)
return false;
Py_DECREF(enumItem);
return true;
@@ -506,15 +441,17 @@ bool createScopedEnumItem(PyTypeObject *enumType, PyTypeObject *scope,
bool createScopedEnumItem(PyTypeObject* enumType, SbkObjectType* scope, const char* itemName, long itemValue)
{
- return createScopedEnumItem(enumType, &scope->super.ht_type, itemName, itemValue);
+ return createScopedEnumItem(enumType, reinterpret_cast<PyTypeObject *>(scope), itemName, itemValue);
}
-PyObject* newItem(PyTypeObject* enumType, long itemValue, const char* itemName)
+PyObject *
+newItem(PyTypeObject *enumType, long itemValue, const char *itemName)
{
bool newValue = true;
SbkEnumObject* enumObj;
if (!itemName) {
- enumObj = reinterpret_cast<SbkEnumObject*>(getEnumItemFromValue(enumType, itemValue));
+ enumObj = reinterpret_cast<SbkEnumObject*>(
+ getEnumItemFromValue(enumType, itemValue));
if (enumObj)
return reinterpret_cast<PyObject*>(enumObj);
@@ -529,10 +466,10 @@ PyObject* newItem(PyTypeObject* enumType, long itemValue, const char* itemName)
enumObj->ob_value = itemValue;
if (newValue) {
- PyObject* values = PyDict_GetItemString(enumType->tp_dict, const_cast<char*>("values"));
+ PyObject* values = PyDict_GetItemString(PepType(enumType)->tp_dict, const_cast<char*>("values"));
if (!values) {
values = PyDict_New();
- PyDict_SetItemString(enumType->tp_dict, const_cast<char*>("values"), values);
+ PyDict_SetItemString(PepType(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));
@@ -541,39 +478,140 @@ PyObject* newItem(PyTypeObject* enumType, long itemValue, const char* itemName)
return reinterpret_cast<PyObject*>(enumObj);
}
-PyTypeObject* newType(const char* name)
-{
- return newTypeWithName(name, "");
-}
+static PyType_Slot SbkNewType_slots[] = {
+ {Py_tp_repr, (void *)SbkEnumObject_repr},
+ {Py_tp_str, (void *)SbkEnumObject_repr},
+ {Py_tp_getset, (void *)SbkEnumGetSetList},
+ {Py_tp_new, (void *)SbkEnum_tp_new},
+ {Py_nb_add, (void *)enum_add},
+ {Py_nb_subtract, (void *)enum_subtract},
+ {Py_nb_multiply, (void *)enum_multiply},
+#ifndef IS_PY3K
+ {Py_nb_divide, (void *)enum_divide},
+#endif
+ {Py_nb_positive, (void *)enum_int},
+#ifdef IS_PY3K
+ {Py_nb_bool, (void *)enum_bool},
+#else
+ {Py_nb_nonzero, (void *)enum_bool},
+ {Py_nb_long, (void *)enum_int},
+#endif
+ {Py_nb_and, (void *)enum_and},
+ {Py_nb_xor, (void *)enum_xor},
+ {Py_nb_or, (void *)enum_or},
+ {Py_nb_int, (void *)enum_int},
+ {Py_nb_index, (void *)enum_int},
+ {Py_tp_richcompare, (void *)enum_richcompare},
+ {Py_tp_hash, (void *)enum_hash},
+ {Py_tp_dealloc, (void *)SbkDummyDealloc},
+ {0, 0}
+};
+static PyType_Spec SbkNewType_spec = {
+ "missing Enum name", // to be inserted later
+ sizeof(SbkEnumObject),
+ 0,
+ Py_TPFLAGS_DEFAULT|Py_TPFLAGS_CHECKTYPES,
+ SbkNewType_slots,
+};
-PyTypeObject* newTypeWithName(const char* name, const char* cppName)
+static void
+copyNumberMethods(PyTypeObject *flagsType,
+ PyType_Slot number_slots[],
+ int *pidx)
{
- 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;
+ int idx = *pidx;
+#ifdef IS_PY3K
+# define SLOT slot
+#else
+# define SLOT slot_
+#endif
+#define PUT_SLOT(name) \
+ number_slots[idx].SLOT = (name); \
+ number_slots[idx].pfunc = PyType_GetSlot(flagsType, (name)); \
+ ++idx;
+
+ PUT_SLOT(Py_nb_absolute);
+ PUT_SLOT(Py_nb_add);
+ PUT_SLOT(Py_nb_and);
+#ifdef IS_PY3K
+ PUT_SLOT(Py_nb_bool);
+#else
+ PUT_SLOT(Py_nb_nonzero);
+#endif
+ PUT_SLOT(Py_nb_divmod);
+ PUT_SLOT(Py_nb_float);
+ PUT_SLOT(Py_nb_floor_divide);
+ PUT_SLOT(Py_nb_index);
+ PUT_SLOT(Py_nb_inplace_add);
+ PUT_SLOT(Py_nb_inplace_and);
+ PUT_SLOT(Py_nb_inplace_floor_divide);
+ PUT_SLOT(Py_nb_inplace_lshift);
+ PUT_SLOT(Py_nb_inplace_multiply);
+ PUT_SLOT(Py_nb_inplace_or);
+ PUT_SLOT(Py_nb_inplace_power);
+ PUT_SLOT(Py_nb_inplace_remainder);
+ PUT_SLOT(Py_nb_inplace_rshift);
+ PUT_SLOT(Py_nb_inplace_subtract);
+ PUT_SLOT(Py_nb_inplace_true_divide);
+ PUT_SLOT(Py_nb_inplace_xor);
+ PUT_SLOT(Py_nb_int);
+ PUT_SLOT(Py_nb_invert);
+ PUT_SLOT(Py_nb_lshift);
+ PUT_SLOT(Py_nb_multiply);
+ PUT_SLOT(Py_nb_negative);
+ PUT_SLOT(Py_nb_or);
+ PUT_SLOT(Py_nb_positive);
+ PUT_SLOT(Py_nb_power);
+ PUT_SLOT(Py_nb_remainder);
+ PUT_SLOT(Py_nb_rshift);
+ PUT_SLOT(Py_nb_subtract);
+ PUT_SLOT(Py_nb_true_divide);
+ PUT_SLOT(Py_nb_xor);
+#ifndef IS_PY3K
+ PUT_SLOT(Py_nb_long);
+ PUT_SLOT(Py_nb_divide);
+#endif
+#undef PUT_SLOT
+ *pidx = idx;
+}
+
+PyTypeObject *
+newTypeWithName(const char* name,
+ const char* cppName,
+ PyTypeObject *numbers_fromFlag)
+{
+ // Careful: PyType_FromSpec does not allocate the string.
+ PyType_Slot newslots[99] = {}; // enough but not too big for the stack
+ PyType_Spec *newspec = new PyType_Spec;
+ newspec->name = strdup(name);
+ newspec->basicsize = SbkNewType_spec.basicsize;
+ newspec->itemsize = SbkNewType_spec.itemsize;
+ newspec->flags = SbkNewType_spec.flags;
+ // we must append all the number methods, so rebuild everything:
+ int idx = 0;
+ while (SbkNewType_slots[idx].SLOT) {
+ newslots[idx].SLOT = SbkNewType_slots[idx].SLOT;
+ newslots[idx].pfunc = SbkNewType_slots[idx].pfunc;
+ ++idx;
+ }
+ if (numbers_fromFlag)
+ copyNumberMethods(numbers_fromFlag, newslots, &idx);
+ newspec->slots = newslots;
+ PyTypeObject *type = reinterpret_cast<PyTypeObject *>(PyType_FromSpec(newspec));
+ Py_TYPE(type) = SbkEnumType_TypeF();
+ Py_INCREF(Py_TYPE(type));
SbkEnumType* enumType = reinterpret_cast<SbkEnumType*>(type);
- enumType->cppName = cppName;
- enumType->converterPtr = &enumType->converter;
+ PepType_SETP(enumType)->cppName = cppName;
+ PepType_SETP(enumType)->converterPtr = &PepType_SETP(enumType)->converter;
DeclaredEnumTypes::instance().addEnumType(type);
return type;
}
const char* getCppName(PyTypeObject* enumType)
{
- assert(Py_TYPE(enumType) == &SbkEnumType_Type);
- return reinterpret_cast<SbkEnumType*>(enumType)->cppName;;
+ assert(Py_TYPE(enumType) == SbkEnumType_TypeF());
+ return PepType_SETP(reinterpret_cast<SbkEnumType*>(enumType))->cppName;
}
long int getValue(PyObject* enumItem)
@@ -585,13 +623,13 @@ long int getValue(PyObject* enumItem)
void setTypeConverter(PyTypeObject* enumType, SbkConverter* converter)
{
//reinterpret_cast<SbkEnumType*>(enumType)->converter = converter;
- SBK_CONVERTER(enumType) = converter;
+ *PepType_SGTP(enumType)->converter = converter;
}
SbkConverter* getTypeConverter(PyTypeObject* enumType)
{
//return reinterpret_cast<SbkEnumType*>(enumType)->converter;
- return SBK_CONVERTER(enumType);
+ return *PepType_SGTP(enumType)->converter;
}
} // namespace Enum
@@ -609,8 +647,17 @@ DeclaredEnumTypes::DeclaredEnumTypes()
DeclaredEnumTypes::~DeclaredEnumTypes()
{
std::list<PyTypeObject*>::const_iterator it = m_enumTypes.begin();
- for (; it != m_enumTypes.end(); ++it)
- delete *it;
+ for (; it != m_enumTypes.end(); ++it) {
+ /*
+ * PYSIDE-595: This was "delete *it;" before introducing 'PyType_FromSpec'.
+ * XXX what should I do now?
+ * Refcounts in tests are 30 or 0 at end.
+ * When I add the default tp_dealloc, we get negative refcounts!
+ * So right now I am doing nothing. Surely wrong but no crash.
+ * See also the comment in function 'createGlobalEnumItem'.
+ */
+ //fprintf(stderr, "ttt %d %s\n", Py_REFCNT(*it), PepType(*it)->tp_name);
+ }
m_enumTypes.clear();
}
diff --git a/sources/shiboken2/libshiboken/sbkenum.h b/sources/shiboken2/libshiboken/sbkenum.h
index 4e466542..c1ec7c4c 100644
--- a/sources/shiboken2/libshiboken/sbkenum.h
+++ b/sources/shiboken2/libshiboken/sbkenum.h
@@ -46,9 +46,11 @@
extern "C"
{
-extern LIBSHIBOKEN_API PyTypeObject SbkEnumType_Type;
+extern LIBSHIBOKEN_API PyTypeObject *SbkEnumType_TypeF(void);
struct SbkObjectType;
struct SbkConverter;
+struct SbkEnumType;
+struct SbkEnumTypePrivate;
} // extern "C"
@@ -57,7 +59,7 @@ namespace Shiboken
inline bool isShibokenEnum(PyObject* pyObj)
{
- return Py_TYPE(pyObj->ob_type) == &SbkEnumType_Type;
+ return Py_TYPE(Py_TYPE(pyObj)) == SbkEnumType_TypeF();
}
namespace Enum
@@ -101,9 +103,8 @@ namespace Enum
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 PyTypeObject* newTypeWithName(const char* name, const char* cppName,
+ PyTypeObject *numbers_fromFlag=nullptr);
LIBSHIBOKEN_API const char* getCppName(PyTypeObject* type);
LIBSHIBOKEN_API long getValue(PyObject* enumItem);
diff --git a/sources/shiboken2/libshiboken/sbkpython.h b/sources/shiboken2/libshiboken/sbkpython.h
index 6d90f408..5fe364a2 100644
--- a/sources/shiboken2/libshiboken/sbkpython.h
+++ b/sources/shiboken2/libshiboken/sbkpython.h
@@ -1,6 +1,6 @@
/****************************************************************************
**
-** Copyright (C) 2016 The Qt Company Ltd.
+** Copyright (C) 2018 The Qt Company Ltd.
** Contact: https://www.qt.io/licensing/
**
** This file is part of Qt for Python.
@@ -40,8 +40,15 @@
#ifndef SBKPYTHON_H
#define SBKPYTHON_H
-#include "Python.h"
+#include "sbkversion.h"
+
+#include <Python.h>
+#include <structmember.h>
+// Now we have the usual variables from Python.h .
#include "python25compat.h"
+#include "shibokenmacros.h"
+#include "pep384impl.h"
+#include "typespec.h"
#if PY_MAJOR_VERSION >= 3
#define IS_PY3K
diff --git a/sources/shiboken2/libshiboken/sbkstring.cpp b/sources/shiboken2/libshiboken/sbkstring.cpp
index 58f58d28..b9267438 100644
--- a/sources/shiboken2/libshiboken/sbkstring.cpp
+++ b/sources/shiboken2/libshiboken/sbkstring.cpp
@@ -1,6 +1,6 @@
/****************************************************************************
**
-** Copyright (C) 2016 The Qt Company Ltd.
+** Copyright (C) 2018 The Qt Company Ltd.
** Contact: https://www.qt.io/licensing/
**
** This file is part of Qt for Python.
@@ -108,7 +108,7 @@ const char* toCString(PyObject* str, Py_ssize_t* len)
}
// Return unicode from str instead of uniStr, because the lifetime of the returned pointer
// depends on the lifetime of str.
- return _PyUnicode_AsString(str);
+ return _PepUnicode_AsString(str);
}
#endif
if (PyBytes_Check(str)) {
diff --git a/sources/shiboken2/libshiboken/sbkversion.h.in b/sources/shiboken2/libshiboken/sbkversion.h.in
index 447376c1..99ee7f93 100644
--- a/sources/shiboken2/libshiboken/sbkversion.h.in
+++ b/sources/shiboken2/libshiboken/sbkversion.h.in
@@ -46,5 +46,8 @@
#define SHIBOKEN_MICRO_VERSION @shiboken_MICRO_VERSION@
#define SHIBOKEN_RELEASE_LEVEL "final"
#define SHIBOKEN_SERIAL 0
+#define PYTHON_VERSION_MAJOR @PYTHON_VERSION_MAJOR@
+#define PYTHON_VERSION_MINOR @PYTHON_VERSION_MINOR@
+#define PYTHON_VERSION_PATCH @PYTHON_VERSION_PATCH@
#endif
diff --git a/sources/shiboken2/libshiboken/shibokenbuffer.cpp b/sources/shiboken2/libshiboken/shibokenbuffer.cpp
index 2404aeb6..05b68dad 100644
--- a/sources/shiboken2/libshiboken/shibokenbuffer.cpp
+++ b/sources/shiboken2/libshiboken/shibokenbuffer.cpp
@@ -84,7 +84,9 @@ PyObject* Shiboken::Buffer::newObject(void* memory, Py_ssize_t size, Type type)
view.itemsize = sizeof(char);
Py_ssize_t shape[] = { size };
view.shape = shape;
- return PyMemoryView_FromBuffer(&view);
+ // Pep384: This is way too complicated and impossible with the limited api:
+ //return PyMemoryView_FromBuffer(&view);
+ return PyMemoryView_FromMemory((char *)view.buf, size, type == ReadOnly ? PyBUF_READ : PyBUF_WRITE);
#else
return type == ReadOnly ? PyBuffer_FromMemory(memory, size) : PyBuffer_FromReadWriteMemory(memory, size);
#endif
diff --git a/sources/shiboken2/libshiboken/signature.cpp b/sources/shiboken2/libshiboken/signature.cpp
index b266784c..fc83f89c 100644
--- a/sources/shiboken2/libshiboken/signature.cpp
+++ b/sources/shiboken2/libshiboken/signature.cpp
@@ -114,7 +114,7 @@ extern "C"
#if EXTENSION_ENABLED
// These constants were needed in former versions of the module:
-#define PYTHON_HAS_QUALNAME (PY_VERSION_HEX >= 0x03060000)
+#define PYTHON_HAS_QUALNAME (PY_VERSION_HEX >= 0x03030000)
#define PYTHON_HAS_UNICODE (PY_VERSION_HEX >= 0x03000000)
#define PYTHON_HAS_WEAKREF_PYCFUNCTION (PY_VERSION_HEX >= 0x030500A0)
#define PYTHON_IS_PYTHON3 (PY_VERSION_HEX >= 0x03000000)
@@ -124,15 +124,16 @@ extern "C"
#define PYTHON_HAS_METH_REDUCE (PYTHON_HAS_DESCR_REDUCE)
#define PYTHON_NEEDS_ITERATOR_FLAG (!PYTHON_IS_PYTHON3)
#define PYTHON_EXPOSES_METHODDESCR (PYTHON_IS_PYTHON3)
+#define PYTHON_NO_TYPE_IN_FUNCTIONS (!PYTHON_IS_PYTHON3 || Py_LIMITED_API)
// These constants are still in use:
#define PYTHON_USES_D_COMMON (PY_VERSION_HEX >= 0x03020000)
-#define PYTHON_NO_TYPE_IN_FUNCTIONS (!PYTHON_IS_PYTHON3)
typedef struct safe_globals_struc {
// init part 1: get arg_dict
PyObject *helper_module;
PyObject *arg_dict;
+ PyObject *map_dict;
// init part 2: run module
PyObject *sigparse_func;
PyObject *createsig_func;
@@ -164,9 +165,9 @@ CreateSignature(PyObject *props, const char *sig_kind)
}
static PyObject *
-pyside_cf_get___signature__(PyCFunctionObject *func)
+pyside_cf_get___signature__(PyObject *func)
{
- return GetSignature_Function(func);
+ return GetSignature_Function((PyCFunctionObject *)func);
}
static PyObject *
@@ -180,22 +181,107 @@ pyside_sm_get___signature__(PyObject *sm)
return ret;
}
+#ifdef Py_LIMITED_API
+
+static int
+build_qualname_to_func(PyObject *obtype)
+{
+ PyTypeObject *type = (PyTypeObject *)obtype;
+ PyMethodDef *meth = PepType(type)->tp_methods;
+
+ if (meth == 0)
+ return 0;
+
+ for (; meth->ml_name != NULL; meth++) {
+ PyObject *func = PyCFunction_NewEx(meth, obtype, NULL);
+ PyObject *qualname = PyObject_GetAttrString(func, "__qualname__");
+ if (func == NULL || qualname == NULL) {
+ return -1;
+ }
+ if (PyDict_SetItem(pyside_globals->map_dict, qualname, func) < 0) {
+ return -1;
+ }
+ Py_DECREF(func);
+ Py_DECREF(qualname);
+ }
+ return 0;
+}
+
static PyObject *
-pyside_md_get___signature__(PyMethodDescrObject *descr)
+qualname_to_typename(PyObject *qualname)
{
- PyCFunctionObject *func;
- PyObject *result;
+ PyObject *func = PyObject_GetAttrString(qualname, "split");
+ PyObject *list = func ? PyObject_CallFunction(func, (char *)"(s)", ".")
+ : NULL;
+ PyObject *res = list ? PyList_GetItem(list, 0) : NULL;
+ Py_XINCREF(res);
+ Py_XDECREF(func);
+ Py_XDECREF(list);
+ return res;
+}
+
+static PyObject *
+qualname_to_func(PyObject *ob)
+{
+ /*
+ * If we have __qualname__, then we can easily build a mapping
+ * from __qualname__ to PyCFunction. This is necessary when
+ * the limited API does not let us go easily from descriptor
+ * to PyMethodDef.
+ */
+ PyObject *ret;
+ PyObject *qualname = PyObject_GetAttrString((PyObject *)ob,
+ "__qualname__");
+ if (qualname != NULL) {
+ ret = PyDict_GetItem(pyside_globals->map_dict, qualname);
+ if (ret == NULL) {
+ // do a lazy initialization
+ PyObject *type_name = qualname_to_typename(qualname);
+ PyObject *type = PyDict_GetItem(pyside_globals->map_dict,
+ type_name);
+ Py_XDECREF(type_name);
+ if (type == NULL)
+ Py_RETURN_NONE;
+ if (build_qualname_to_func(type) < 0)
+ return NULL;
+ ret = PyDict_GetItem(pyside_globals->map_dict, qualname);
+ }
+ Py_XINCREF(ret);
+ Py_DECREF(qualname);
+ }
+ else
+ Py_RETURN_NONE;
+ return ret;
+}
+#endif
- func = (PyCFunctionObject *)
- PyCFunction_NewEx(descr->d_method,
-#if PYTHON_USES_D_COMMON
- (PyObject *)descr->d_common.d_type, NULL
+static PyObject *
+pyside_md_get___signature__(PyObject *ob)
+{
+ PyObject *func;
+ PyObject *result;
+#ifndef Py_LIMITED_API
+ PyMethodDescrObject *descr = (PyMethodDescrObject *)ob;
+
+# if PYTHON_USES_D_COMMON
+ func = PyCFunction_NewEx(descr->d_method,
+ (PyObject *)descr->d_common.d_type, NULL);
+# else
+ func = PyCFunction_NewEx(descr->d_method,
+ (PyObject *)descr->d_type, NULL);
+# endif
#else
- (PyObject *)descr->d_type, NULL
+ /*
+ * With limited access, we cannot use the fields of a method descriptor,
+ * but in Python 3 we have the __qualname__ field which allows us to
+ * grab the method object from our registry.
+ */
+ func = qualname_to_func(ob);
#endif
- );
+ if (func == Py_None)
+ return Py_None;
if (func == NULL)
- return NULL;
+ Py_FatalError("missing mapping in MethodDescriptor");
result = pyside_cf_get___signature__(func);
Py_DECREF(func);
return result;
@@ -215,16 +301,15 @@ GetSignature_Function(PyCFunctionObject *func)
const char *sig_kind;
int flags;
- selftype = func->m_self;
- if (selftype == NULL) {
-#if PYTHON_NO_TYPE_IN_FUNCTIONS
- selftype = PyDict_GetItem(pyside_globals->arg_dict, (PyObject *)func);
- }
+ selftype = PyCFunction_GET_SELF((PyObject *)func);
+ if (selftype == NULL)
+ selftype = PyDict_GetItem(pyside_globals->map_dict, (PyObject *)func);
if (selftype == NULL) {
-#endif
if (!PyErr_Occurred()) {
PyErr_Format(PyExc_SystemError,
- "the signature for \"%s\" should exist", func->m_ml->ml_name);
+ "the signature for \"%s\" should exist",
+ PepCFunction_GET_NAMESTR(func)
+ );
}
return NULL;
}
@@ -251,7 +336,7 @@ GetSignature_Function(PyCFunctionObject *func)
props = PyDict_GetItem(dict, func_name);
if (props == NULL)
Py_RETURN_NONE;
- flags = PyCFunction_GET_FLAGS(func);
+ flags = PyCFunction_GET_FLAGS((PyObject *)func);
if (flags & METH_CLASS)
sig_kind = "classmethod";
else if (flags & METH_STATIC)
@@ -347,6 +432,11 @@ init_phase_1(void)
goto error;
Py_DECREF(v);
+ // build a dict for diverse mappings
+ p->map_dict = PyDict_New();
+ if (p->map_dict == NULL)
+ goto error;
+
// Build a dict for the prepared arguments
p->arg_dict = PyDict_New();
if (p->arg_dict == NULL)
@@ -387,7 +477,7 @@ error:
static int
add_more_getsets(PyTypeObject *type, PyGetSetDef *gsp)
{
- PyObject *dict = type->tp_dict;
+ PyObject *dict = PepType(type)->tp_dict;
for (; gsp->name != NULL; gsp++) {
PyObject *descr;
@@ -479,16 +569,17 @@ PySideType_Ready(PyTypeObject *type)
// PyMethodDescr_Type 'type(str.__dict__["split"])'
// PyClassMethodDescr_Type. 'type(dict.__dict__["fromkeys"])'
// The latter is not needed until we use class methods in PySide.
- md = PyDict_GetItemString(PyString_Type.tp_dict, "split");
+ md = PyObject_GetAttrString((PyObject *)&PyString_Type, "split");
if (md == NULL
|| PyType_Ready(Py_TYPE(md)) < 0
|| add_more_getsets(Py_TYPE(md), new_PyMethodDescr_getsets) < 0
|| add_more_getsets(&PyCFunction_Type, new_PyCFunction_getsets) < 0
- || add_more_getsets(&PyStaticMethod_Type, new_PyStaticMethod_getsets) < 0
+ || add_more_getsets(PepStaticMethod_TypePtr, new_PyStaticMethod_getsets) < 0
|| add_more_getsets(&PyType_Type, new_PyType_getsets) < 0)
return -1;
+ Py_DECREF(md);
#ifndef _WIN32
- // we enable the stack trace in CI, only.
+ // We enable the stack trace in CI, only.
const char *testEnv = getenv("QTEST_ENVIRONMENT");
if (testEnv && strstr(testEnv, "ci"))
signal(SIGSEGV, handler); // install our handler
@@ -498,20 +589,12 @@ PySideType_Ready(PyTypeObject *type)
return PyType_Ready(type);
}
-#if PYTHON_NO_TYPE_IN_FUNCTIONS
-
-typedef struct {
- PyObject_HEAD
- PyObject *sm_callable;
- PyObject *sm_dict;
-} staticmethod;
-
static int
build_func_to_type(PyObject *obtype)
{
PyTypeObject *type = (PyTypeObject *)obtype;
- PyObject *dict = type->tp_dict;
- PyMethodDef *meth = type->tp_methods;
+ PyObject *dict = PepType(type)->tp_dict;
+ PyMethodDef *meth = PepType(type)->tp_methods;
if (meth == 0)
return 0;
@@ -521,19 +604,16 @@ build_func_to_type(PyObject *obtype)
PyObject *descr = PyDict_GetItemString(dict, meth->ml_name);
if (descr == NULL)
return -1;
- staticmethod *sm = (staticmethod *)descr;
- PyObject *cfunc = sm->sm_callable;
- if (cfunc == NULL)
- return -1;
- if (PyDict_SetItem(pyside_globals->arg_dict, cfunc, obtype) < 0)
+ PyObject *func = PyObject_GetAttrString(descr, "__func__");
+ if (func == NULL ||
+ PyDict_SetItem(pyside_globals->map_dict, func, obtype) < 0)
return -1;
+ Py_DECREF(func);
}
}
return 0;
}
-#endif
-
static int
PySide_BuildSignatureArgs(PyObject *module, PyObject *type,
const char *signatures)
@@ -574,6 +654,12 @@ PySide_BuildSignatureArgs(PyObject *module, PyObject *type,
return -1;
if (PyDict_SetItem(pyside_globals->arg_dict, type_name, arg_tup) < 0)
return -1;
+ /*
+ * We record also a mapping from type name to type. This helps to lazily
+ * initialize the Py_LIMITED_API in qualname_to_func().
+ */
+ if (PyDict_SetItem(pyside_globals->map_dict, type_name, type) < 0)
+ return -1;
return 0;
}
@@ -650,13 +736,16 @@ PySide_FinishSignatures(PyObject *module, const char *signatures)
if (PySide_BuildSignatureArgs(module, module, signatures) < 0)
return -1;
-#if PYTHON_NO_TYPE_IN_FUNCTIONS
/*
* Python2 does not abuse the 'm_self' field for the type. So we need to
* supply this for all static methods.
*
* Note: This function crashed when called from PySide_BuildSignatureArgs.
* Probably this was too early.
+ *
+ * Pep384: We need to switch this always on since we have no access
+ * to the PyCFunction attributes. Therefore I simplified things
+ * and always use our own mapping.
*/
{
PyObject *key, *value;
@@ -668,12 +757,12 @@ PySide_FinishSignatures(PyObject *module, const char *signatures)
while (PyDict_Next(dict, &pos, &key, &value)) {
if (PyType_Check(value)) {
- if (build_func_to_type(value) < 0)
+ PyObject *type = value;
+ if (build_func_to_type(type) < 0)
return -1;
}
}
}
-#endif
return 0;
}
#endif // EXTENSION_ENABLED
diff --git a/sources/shiboken2/libshiboken/tmp-referencetopython/sbkconverter.cpp b/sources/shiboken2/libshiboken/tmp-referencetopython/sbkconverter.cpp
index 7c20b9b5..8e351ced 100644
--- a/sources/shiboken2/libshiboken/tmp-referencetopython/sbkconverter.cpp
+++ b/sources/shiboken2/libshiboken/tmp-referencetopython/sbkconverter.cpp
@@ -180,7 +180,7 @@ void pythonToCppPointer(SbkObjectType* type, PyObject* pyIn, void* cppOut)
{
assert(pyIn);
assert(cppOut);
- SbkObjectType* inType = (SbkObjectType*)pyIn->ob_type;
+ SbkObjectType* inType = (SbkObjectType*)Py_TYPE(pyIn);
if (ObjectType::hasCast(inType))
*((void**)cppOut) = ObjectType::cast(inType, (SbkObject*)pyIn, (PyTypeObject*)type);
else
diff --git a/sources/shiboken2/libshiboken/tmp-referencetopython/sbkconverter.h b/sources/shiboken2/libshiboken/tmp-referencetopython/sbkconverter.h
index f139a491..cc9ea7a1 100644
--- a/sources/shiboken2/libshiboken/tmp-referencetopython/sbkconverter.h
+++ b/sources/shiboken2/libshiboken/tmp-referencetopython/sbkconverter.h
@@ -41,7 +41,7 @@
#define SBK_CONVERTER_H
#include <limits>
-#include <Python.h>
+#include "sbkpython.h"
#include "shibokenmacros.h"
#include "basewrapper.h"
diff --git a/sources/shiboken2/libshiboken/typespec.cpp b/sources/shiboken2/libshiboken/typespec.cpp
new file mode 100644
index 00000000..d532c97e
--- /dev/null
+++ b/sources/shiboken2/libshiboken/typespec.cpp
@@ -0,0 +1,776 @@
+/****************************************************************************
+**
+** Copyright (C) 2018 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of Qt for Python.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 3 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL3 included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 3 requirements
+** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 2.0 or (at your option) the GNU General
+** Public license version 3 or any later version approved by the KDE Free
+** Qt Foundation. The licenses are as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-2.0.html and
+** https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "typespec.h"
+#include <structmember.h>
+
+#if PY_MAJOR_VERSION < 3
+
+extern "C"
+{
+
+// for some reason python 2.7 needs this on Windows
+#ifdef WIN32
+static PyGC_Head *_PyGC_generation0;
+#endif
+
+// from pymacro.h
+#ifndef Py_PYMACRO_H
+#define Py_PYMACRO_H
+
+/* Minimum value between x and y */
+#define Py_MIN(x, y) (((x) > (y)) ? (y) : (x))
+
+/* Maximum value between x and y */
+#define Py_MAX(x, y) (((x) > (y)) ? (x) : (y))
+
+/* Absolute value of the number x */
+#define Py_ABS(x) ((x) < 0 ? -(x) : (x))
+
+#define _Py_XSTRINGIFY(x) #x
+
+/* Convert the argument to a string. For example, Py_STRINGIFY(123) is replaced
+ with "123" by the preprocessor. Defines are also replaced by their value.
+ For example Py_STRINGIFY(__LINE__) is replaced by the line number, not
+ by "__LINE__". */
+#define Py_STRINGIFY(x) _Py_XSTRINGIFY(x)
+
+/* Get the size of a structure member in bytes */
+#define Py_MEMBER_SIZE(type, member) sizeof(((type *)0)->member)
+
+/* Argument must be a char or an int in [-128, 127] or [0, 255]. */
+#define Py_CHARMASK(c) ((unsigned char)((c) & 0xff))
+
+/* Assert a build-time dependency, as an expression.
+
+ Your compile will fail if the condition isn't true, or can't be evaluated
+ by the compiler. This can be used in an expression: its value is 0.
+
+ Example:
+
+ #define foo_to_char(foo) \
+ ((char *)(foo) \
+ + Py_BUILD_ASSERT_EXPR(offsetof(struct foo, string) == 0))
+
+ Written by Rusty Russell, public domain, http://ccodearchive.net/ */
+#define Py_BUILD_ASSERT_EXPR(cond) \
+ (sizeof(char [1 - 2*!(cond)]) - 1)
+
+#define Py_BUILD_ASSERT(cond) do { \
+ (void)Py_BUILD_ASSERT_EXPR(cond); \
+ } while (0)
+
+/* Get the number of elements in a visible array
+
+ This does not work on pointers, or arrays declared as [], or function
+ parameters. With correct compiler support, such usage will cause a build
+ error (see Py_BUILD_ASSERT_EXPR).
+
+ Written by Rusty Russell, public domain, http://ccodearchive.net/
+
+ Requires at GCC 3.1+ */
+// Simplified by "0 &&"
+#if 0 && (defined(__GNUC__) && !defined(__STRICT_ANSI__) && \
+ (((__GNUC__ == 3) && (__GNU_MINOR__ >= 1)) || (__GNUC__ >= 4)))
+/* Two gcc extensions.
+ &a[0] degrades to a pointer: a different type from an array */
+#define Py_ARRAY_LENGTH(array) \
+ (sizeof(array) / sizeof((array)[0]) \
+ + Py_BUILD_ASSERT_EXPR(!__builtin_types_compatible_p(typeof(array), \
+ typeof(&(array)[0]))))
+#else
+#define Py_ARRAY_LENGTH(array) \
+ (sizeof(array) / sizeof((array)[0]))
+#endif
+
+
+/* Define macros for inline documentation. */
+#define PyDoc_VAR(name) static char name[]
+#define PyDoc_STRVAR(name,str) PyDoc_VAR(name) = PyDoc_STR(str)
+#ifdef WITH_DOC_STRINGS
+#define PyDoc_STR(str) str
+#else
+#define PyDoc_STR(str) ""
+#endif
+
+/* Below "a" is a power of 2. */
+/* Round down size "n" to be a multiple of "a". */
+#define _Py_SIZE_ROUND_DOWN(n, a) ((size_t)(n) & ~(size_t)((a) - 1))
+/* Round up size "n" to be a multiple of "a". */
+#define _Py_SIZE_ROUND_UP(n, a) (((size_t)(n) + \
+ (size_t)((a) - 1)) & ~(size_t)((a) - 1))
+/* Round pointer "p" down to the closest "a"-aligned address <= "p". */
+#define _Py_ALIGN_DOWN(p, a) ((void *)((uintptr_t)(p) & ~(uintptr_t)((a) - 1)))
+/* Round pointer "p" up to the closest "a"-aligned address >= "p". */
+#define _Py_ALIGN_UP(p, a) ((void *)(((uintptr_t)(p) + \
+ (uintptr_t)((a) - 1)) & ~(uintptr_t)((a) - 1)))
+/* Check if pointer "p" is aligned to "a"-bytes boundary. */
+#define _Py_IS_ALIGNED(p, a) (!((uintptr_t)(p) & (uintptr_t)((a) - 1)))
+
+#ifdef __GNUC__
+#define Py_UNUSED(name) _unused_ ## name __attribute__((unused))
+#else
+#define Py_UNUSED(name) _unused_ ## name
+#endif
+
+#endif /* Py_PYMACRO_H */
+
+// from typeobject.c
+static int
+extra_ivars(PyTypeObject *type, PyTypeObject *base)
+{
+ size_t t_size = type->tp_basicsize;
+ size_t b_size = base->tp_basicsize;
+
+ assert(t_size >= b_size); /* Else type smaller than base! */
+ if (type->tp_itemsize || base->tp_itemsize) {
+ /* If itemsize is involved, stricter rules */
+ return t_size != b_size ||
+ type->tp_itemsize != base->tp_itemsize;
+ }
+ if (type->tp_weaklistoffset && base->tp_weaklistoffset == 0 &&
+ type->tp_weaklistoffset + sizeof(PyObject *) == t_size &&
+ type->tp_flags & Py_TPFLAGS_HEAPTYPE)
+ t_size -= sizeof(PyObject *);
+ if (type->tp_dictoffset && base->tp_dictoffset == 0 &&
+ type->tp_dictoffset + sizeof(PyObject *) == t_size &&
+ type->tp_flags & Py_TPFLAGS_HEAPTYPE)
+ t_size -= sizeof(PyObject *);
+
+ return t_size != b_size;
+}
+
+static void
+clear_slots(PyTypeObject *type, PyObject *self)
+{
+ Py_ssize_t i, n;
+ PyMemberDef *mp;
+
+ n = Py_SIZE(type);
+ mp = PyHeapType_GET_MEMBERS((PyHeapTypeObject *)type);
+ for (i = 0; i < n; i++, mp++) {
+ if (mp->type == T_OBJECT_EX && !(mp->flags & READONLY)) {
+ char *addr = (char *)self + mp->offset;
+ PyObject *obj = *(PyObject **)addr;
+ if (obj != NULL) {
+ *(PyObject **)addr = NULL;
+ Py_DECREF(obj);
+ }
+ }
+ }
+}
+
+static void
+subtype_dealloc(PyObject *self)
+{
+ PyTypeObject *type, *base;
+ destructor basedealloc;
+ PyThreadState *tstate = PyThreadState_GET();
+
+ /* Extract the type; we expect it to be a heap type */
+ type = Py_TYPE(self);
+ assert(type->tp_flags & Py_TPFLAGS_HEAPTYPE);
+
+ /* Test whether the type has GC exactly once */
+
+ if (!PyType_IS_GC(type)) {
+ /* It's really rare to find a dynamic type that doesn't have
+ GC; it can only happen when deriving from 'object' and not
+ adding any slots or instance variables. This allows
+ certain simplifications: there's no need to call
+ clear_slots(), or DECREF the dict, or clear weakrefs. */
+
+ /* Maybe call finalizer; exit early if resurrected */
+ if (type->tp_del) {
+ type->tp_del(self);
+ if (self->ob_refcnt > 0)
+ return;
+ }
+
+ /* Find the nearest base with a different tp_dealloc */
+ base = type;
+ while ((basedealloc = base->tp_dealloc) == subtype_dealloc) {
+ assert(Py_SIZE(base) == 0);
+ base = base->tp_base;
+ assert(base);
+ }
+
+ /* Extract the type again; tp_del may have changed it */
+ type = Py_TYPE(self);
+
+ /* Call the base tp_dealloc() */
+ assert(basedealloc);
+ basedealloc(self);
+
+ /* Can't reference self beyond this point */
+ Py_DECREF(type);
+
+ /* Done */
+ return;
+ }
+
+ /* We get here only if the type has GC */
+
+ /* UnTrack and re-Track around the trashcan macro, alas */
+ /* See explanation at end of function for full disclosure */
+ PyObject_GC_UnTrack(self);
+ ++_PyTrash_delete_nesting;
+ ++ tstate->trash_delete_nesting;
+ Py_TRASHCAN_SAFE_BEGIN(self);
+ --_PyTrash_delete_nesting;
+ -- tstate->trash_delete_nesting;
+ /* DO NOT restore GC tracking at this point. weakref callbacks
+ * (if any, and whether directly here or indirectly in something we
+ * call) may trigger GC, and if self is tracked at that point, it
+ * will look like trash to GC and GC will try to delete self again.
+ */
+
+ /* Find the nearest base with a different tp_dealloc */
+ base = type;
+ while ((basedealloc = base->tp_dealloc) == subtype_dealloc) {
+ base = base->tp_base;
+ assert(base);
+ }
+
+ /* If we added a weaklist, we clear it. Do this *before* calling
+ the finalizer (__del__), clearing slots, or clearing the instance
+ dict. */
+
+ if (type->tp_weaklistoffset && !base->tp_weaklistoffset)
+ PyObject_ClearWeakRefs(self);
+
+ /* Maybe call finalizer; exit early if resurrected */
+ if (type->tp_del) {
+ _PyObject_GC_TRACK(self);
+ type->tp_del(self);
+ if (self->ob_refcnt > 0)
+ goto endlabel; /* resurrected */
+ else
+ _PyObject_GC_UNTRACK(self);
+ /* New weakrefs could be created during the finalizer call.
+ If this occurs, clear them out without calling their
+ finalizers since they might rely on part of the object
+ being finalized that has already been destroyed. */
+ if (type->tp_weaklistoffset && !base->tp_weaklistoffset) {
+ /* Modeled after GET_WEAKREFS_LISTPTR() */
+ PyWeakReference **list = (PyWeakReference **) \
+ PyObject_GET_WEAKREFS_LISTPTR(self);
+ while (*list)
+ _PyWeakref_ClearRef(*list);
+ }
+ }
+
+ /* Clear slots up to the nearest base with a different tp_dealloc */
+ base = type;
+ while (base->tp_dealloc == subtype_dealloc) {
+ if (Py_SIZE(base))
+ clear_slots(base, self);
+ base = base->tp_base;
+ assert(base);
+ }
+
+ /* If we added a dict, DECREF it */
+ if (type->tp_dictoffset && !base->tp_dictoffset) {
+ PyObject **dictptr = _PyObject_GetDictPtr(self);
+ if (dictptr != NULL) {
+ PyObject *dict = *dictptr;
+ if (dict != NULL) {
+ Py_DECREF(dict);
+ *dictptr = NULL;
+ }
+ }
+ }
+
+ /* Extract the type again; tp_del may have changed it */
+ type = Py_TYPE(self);
+
+ /* Call the base tp_dealloc(); first retrack self if
+ * basedealloc knows about gc.
+ */
+ if (PyType_IS_GC(base))
+ _PyObject_GC_TRACK(self);
+ assert(basedealloc);
+ basedealloc(self);
+
+ /* Can't reference self beyond this point */
+ Py_DECREF(type);
+
+ endlabel:
+ ++_PyTrash_delete_nesting;
+ ++ tstate->trash_delete_nesting;
+ Py_TRASHCAN_SAFE_END(self);
+ --_PyTrash_delete_nesting;
+ -- tstate->trash_delete_nesting;
+
+ /* Explanation of the weirdness around the trashcan macros:
+
+ Q. What do the trashcan macros do?
+
+ A. Read the comment titled "Trashcan mechanism" in object.h.
+ For one, this explains why there must be a call to GC-untrack
+ before the trashcan begin macro. Without understanding the
+ trashcan code, the answers to the following questions don't make
+ sense.
+
+ Q. Why do we GC-untrack before the trashcan and then immediately
+ GC-track again afterward?
+
+ A. In the case that the base class is GC-aware, the base class
+ probably GC-untracks the object. If it does that using the
+ UNTRACK macro, this will crash when the object is already
+ untracked. Because we don't know what the base class does, the
+ only safe thing is to make sure the object is tracked when we
+ call the base class dealloc. But... The trashcan begin macro
+ requires that the object is *untracked* before it is called. So
+ the dance becomes:
+
+ GC untrack
+ trashcan begin
+ GC track
+
+ Q. Why did the last question say "immediately GC-track again"?
+ It's nowhere near immediately.
+
+ A. Because the code *used* to re-track immediately. Bad Idea.
+ self has a refcount of 0, and if gc ever gets its hands on it
+ (which can happen if any weakref callback gets invoked), it
+ looks like trash to gc too, and gc also tries to delete self
+ then. But we're already deleting self. Double deallocation is
+ a subtle disaster.
+
+ Q. Why the bizarre (net-zero) manipulation of
+ _PyTrash_delete_nesting around the trashcan macros?
+
+ A. Some base classes (e.g. list) also use the trashcan mechanism.
+ The following scenario used to be possible:
+
+ - suppose the trashcan level is one below the trashcan limit
+
+ - subtype_dealloc() is called
+
+ - the trashcan limit is not yet reached, so the trashcan level
+ is incremented and the code between trashcan begin and end is
+ executed
+
+ - this destroys much of the object's contents, including its
+ slots and __dict__
+
+ - basedealloc() is called; this is really list_dealloc(), or
+ some other type which also uses the trashcan macros
+
+ - the trashcan limit is now reached, so the object is put on the
+ trashcan's to-be-deleted-later list
+
+ - basedealloc() returns
+
+ - subtype_dealloc() decrefs the object's type
+
+ - subtype_dealloc() returns
+
+ - later, the trashcan code starts deleting the objects from its
+ to-be-deleted-later list
+
+ - subtype_dealloc() is called *AGAIN* for the same object
+
+ - at the very least (if the destroyed slots and __dict__ don't
+ cause problems) the object's type gets decref'ed a second
+ time, which is *BAD*!!!
+
+ The remedy is to make sure that if the code between trashcan
+ begin and end in subtype_dealloc() is called, the code between
+ trashcan begin and end in basedealloc() will also be called.
+ This is done by decrementing the level after passing into the
+ trashcan block, and incrementing it just before leaving the
+ block.
+
+ But now it's possible that a chain of objects consisting solely
+ of objects whose deallocator is subtype_dealloc() will defeat
+ the trashcan mechanism completely: the decremented level means
+ that the effective level never reaches the limit. Therefore, we
+ *increment* the level *before* entering the trashcan block, and
+ matchingly decrement it after leaving. This means the trashcan
+ code will trigger a little early, but that's no big deal.
+
+ Q. Are there any live examples of code in need of all this
+ complexity?
+
+ A. Yes. See SF bug 668433 for code that crashed (when Python was
+ compiled in debug mode) before the trashcan level manipulations
+ were added. For more discussion, see SF patches 581742, 575073
+ and bug 574207.
+ */
+}
+
+static PyTypeObject *
+solid_base(PyTypeObject *type)
+{
+ PyTypeObject *base;
+
+ if (type->tp_base)
+ base = solid_base(type->tp_base);
+ else
+ base = &PyBaseObject_Type;
+ if (extra_ivars(type, base))
+ return type;
+ else
+ return base;
+}
+
+/* Calculate the best base amongst multiple base classes.
+ This is the first one that's on the path to the "solid base". */
+
+static PyTypeObject *
+best_base(PyObject *bases)
+{
+ Py_ssize_t i, n;
+ PyTypeObject *base, *winner, *candidate, *base_i;
+ PyObject *base_proto;
+
+ assert(PyTuple_Check(bases));
+ n = PyTuple_GET_SIZE(bases);
+ assert(n > 0);
+ base = NULL;
+ winner = NULL;
+ for (i = 0; i < n; i++) {
+ base_proto = PyTuple_GET_ITEM(bases, i);
+ if (PyClass_Check(base_proto))
+ continue;
+ if (!PyType_Check(base_proto)) {
+ PyErr_SetString(
+ PyExc_TypeError,
+ "bases must be types");
+ return NULL;
+ }
+ base_i = (PyTypeObject *)base_proto;
+ if (base_i->tp_dict == NULL) {
+ if (PyType_Ready(base_i) < 0)
+ return NULL;
+ }
+ if (!PyType_HasFeature(base_i, Py_TPFLAGS_BASETYPE)) {
+ PyErr_Format(PyExc_TypeError,
+ "type '%.100s' is not an acceptable base type",
+ base_i->tp_name);
+ return NULL;
+ }
+ candidate = solid_base(base_i);
+ if (winner == NULL) {
+ winner = candidate;
+ base = base_i;
+ }
+ else if (PyType_IsSubtype(winner, candidate))
+ ;
+ else if (PyType_IsSubtype(candidate, winner)) {
+ winner = candidate;
+ base = base_i;
+ }
+ else {
+ PyErr_SetString(
+ PyExc_TypeError,
+ "multiple bases have "
+ "instance lay-out conflict");
+ return NULL;
+ }
+ }
+ if (base == NULL)
+ PyErr_SetString(PyExc_TypeError,
+ "a new-style class can't have only classic bases");
+ return base;
+}
+
+static const short slotoffsets[] = {
+ -1, /* invalid slot_ */
+/* Generated by typeslots.py */
+0,
+0,
+offsetof(PyHeapTypeObject, as_mapping.mp_ass_subscript),
+offsetof(PyHeapTypeObject, as_mapping.mp_length),
+offsetof(PyHeapTypeObject, as_mapping.mp_subscript),
+offsetof(PyHeapTypeObject, as_number.nb_absolute),
+offsetof(PyHeapTypeObject, as_number.nb_add),
+offsetof(PyHeapTypeObject, as_number.nb_and),
+offsetof(PyHeapTypeObject, as_number.nb_nonzero),
+offsetof(PyHeapTypeObject, as_number.nb_divmod),
+offsetof(PyHeapTypeObject, as_number.nb_float),
+offsetof(PyHeapTypeObject, as_number.nb_floor_divide),
+offsetof(PyHeapTypeObject, as_number.nb_index),
+offsetof(PyHeapTypeObject, as_number.nb_inplace_add),
+offsetof(PyHeapTypeObject, as_number.nb_inplace_and),
+offsetof(PyHeapTypeObject, as_number.nb_inplace_floor_divide),
+offsetof(PyHeapTypeObject, as_number.nb_inplace_lshift),
+offsetof(PyHeapTypeObject, as_number.nb_inplace_multiply),
+offsetof(PyHeapTypeObject, as_number.nb_inplace_or),
+offsetof(PyHeapTypeObject, as_number.nb_inplace_power),
+offsetof(PyHeapTypeObject, as_number.nb_inplace_remainder),
+offsetof(PyHeapTypeObject, as_number.nb_inplace_rshift),
+offsetof(PyHeapTypeObject, as_number.nb_inplace_subtract),
+offsetof(PyHeapTypeObject, as_number.nb_inplace_true_divide),
+offsetof(PyHeapTypeObject, as_number.nb_inplace_xor),
+offsetof(PyHeapTypeObject, as_number.nb_int),
+offsetof(PyHeapTypeObject, as_number.nb_invert),
+offsetof(PyHeapTypeObject, as_number.nb_lshift),
+offsetof(PyHeapTypeObject, as_number.nb_multiply),
+offsetof(PyHeapTypeObject, as_number.nb_negative),
+offsetof(PyHeapTypeObject, as_number.nb_or),
+offsetof(PyHeapTypeObject, as_number.nb_positive),
+offsetof(PyHeapTypeObject, as_number.nb_power),
+offsetof(PyHeapTypeObject, as_number.nb_remainder),
+offsetof(PyHeapTypeObject, as_number.nb_rshift),
+offsetof(PyHeapTypeObject, as_number.nb_subtract),
+offsetof(PyHeapTypeObject, as_number.nb_true_divide),
+offsetof(PyHeapTypeObject, as_number.nb_xor),
+offsetof(PyHeapTypeObject, as_sequence.sq_ass_item),
+offsetof(PyHeapTypeObject, as_sequence.sq_concat),
+offsetof(PyHeapTypeObject, as_sequence.sq_contains),
+offsetof(PyHeapTypeObject, as_sequence.sq_inplace_concat),
+offsetof(PyHeapTypeObject, as_sequence.sq_inplace_repeat),
+offsetof(PyHeapTypeObject, as_sequence.sq_item),
+offsetof(PyHeapTypeObject, as_sequence.sq_length),
+offsetof(PyHeapTypeObject, as_sequence.sq_repeat),
+offsetof(PyHeapTypeObject, ht_type.tp_alloc),
+offsetof(PyHeapTypeObject, ht_type.tp_base),
+offsetof(PyHeapTypeObject, ht_type.tp_bases),
+offsetof(PyHeapTypeObject, ht_type.tp_call),
+offsetof(PyHeapTypeObject, ht_type.tp_clear),
+offsetof(PyHeapTypeObject, ht_type.tp_dealloc),
+offsetof(PyHeapTypeObject, ht_type.tp_del),
+offsetof(PyHeapTypeObject, ht_type.tp_descr_get),
+offsetof(PyHeapTypeObject, ht_type.tp_descr_set),
+offsetof(PyHeapTypeObject, ht_type.tp_doc),
+offsetof(PyHeapTypeObject, ht_type.tp_getattr),
+offsetof(PyHeapTypeObject, ht_type.tp_getattro),
+offsetof(PyHeapTypeObject, ht_type.tp_hash),
+offsetof(PyHeapTypeObject, ht_type.tp_init),
+offsetof(PyHeapTypeObject, ht_type.tp_is_gc),
+offsetof(PyHeapTypeObject, ht_type.tp_iter),
+offsetof(PyHeapTypeObject, ht_type.tp_iternext),
+offsetof(PyHeapTypeObject, ht_type.tp_methods),
+offsetof(PyHeapTypeObject, ht_type.tp_new),
+offsetof(PyHeapTypeObject, ht_type.tp_repr),
+offsetof(PyHeapTypeObject, ht_type.tp_richcompare),
+offsetof(PyHeapTypeObject, ht_type.tp_setattr),
+offsetof(PyHeapTypeObject, ht_type.tp_setattro),
+offsetof(PyHeapTypeObject, ht_type.tp_str),
+offsetof(PyHeapTypeObject, ht_type.tp_traverse),
+offsetof(PyHeapTypeObject, ht_type.tp_members),
+offsetof(PyHeapTypeObject, ht_type.tp_getset),
+offsetof(PyHeapTypeObject, ht_type.tp_free),
+offsetof(PyHeapTypeObject, as_number.nb_long),
+offsetof(PyHeapTypeObject, as_number.nb_divide),
+offsetof(PyHeapTypeObject, as_sequence.sq_slice),
+};
+
+PyObject *
+PyType_FromSpecWithBases(PyType_Spec *spec, PyObject *bases)
+{
+ PyHeapTypeObject *res = (PyHeapTypeObject*)PyType_GenericAlloc(&PyType_Type, 0);
+ PyTypeObject *type, *base;
+ PyObject *modname;
+ char *s;
+ char *res_start = (char*)res;
+ PyType_Slot *slot_;
+
+ /* Set the type name and qualname */
+ s = (char *)strrchr(spec->name, '.'); // C++11
+ if (s == NULL)
+ s = (char*)spec->name;
+ else
+ s++;
+
+ if (res == NULL)
+ return NULL;
+ type = &res->ht_type;
+ /* The flags must be initialized early, before the GC traverses us */
+ type->tp_flags = spec->flags | Py_TPFLAGS_HEAPTYPE;
+ // was PyUnicode_FromString in Python 3
+ res->ht_name = PyString_FromString(s);
+ if (!res->ht_name)
+ goto fail;
+ // no ht_qualname in Python 2
+ // res->ht_qualname = res->ht_name;
+ // Py_INCREF(res->ht_qualname);
+ type->tp_name = spec->name;
+ if (!type->tp_name)
+ goto fail;
+
+ /* Adjust for empty tuple bases */
+ if (!bases) {
+ base = &PyBaseObject_Type;
+ /* See whether Py_tp_base(s) was specified */
+ for (slot_ = spec->slots; slot_->slot_; slot_++) {
+ if (slot_->slot_ == Py_tp_base)
+ base = (PyTypeObject *)slot_->pfunc; // C++11
+ else if (slot_->slot_ == Py_tp_bases) {
+ bases = (PyObject *)slot_->pfunc; // C++11
+ Py_INCREF(bases);
+ }
+ }
+ if (!bases)
+ bases = PyTuple_Pack(1, base);
+ if (!bases)
+ goto fail;
+ }
+ else
+ Py_INCREF(bases);
+
+ /* Calculate best base, and check that all bases are type objects */
+ base = best_base(bases);
+ if (base == NULL) {
+ goto fail;
+ }
+ if (!PyType_HasFeature(base, Py_TPFLAGS_BASETYPE)) {
+ PyErr_Format(PyExc_TypeError,
+ "type '%.100s' is not an acceptable base type",
+ base->tp_name);
+ goto fail;
+ }
+
+ /* Initialize essential fields */
+ // no async in Python 2
+ // type->tp_as_async = &res->as_async;
+ type->tp_as_number = &res->as_number;
+ type->tp_as_sequence = &res->as_sequence;
+ type->tp_as_mapping = &res->as_mapping;
+ type->tp_as_buffer = &res->as_buffer;
+ /* Set tp_base and tp_bases */
+ type->tp_bases = bases;
+ bases = NULL;
+ Py_INCREF(base);
+ type->tp_base = base;
+
+ type->tp_basicsize = spec->basicsize;
+ type->tp_itemsize = spec->itemsize;
+
+ for (slot_ = spec->slots; slot_->slot_; slot_++) {
+ if (slot_->slot_ < 0
+ || (size_t)slot_->slot_ >= Py_ARRAY_LENGTH(slotoffsets)) {
+ PyErr_SetString(PyExc_RuntimeError, "invalid slot_ offset");
+ goto fail;
+ }
+ if (slot_->slot_ == Py_tp_base || slot_->slot_ == Py_tp_bases)
+ /* Processed above */
+ continue;
+ *(void**)(res_start + slotoffsets[slot_->slot_]) = slot_->pfunc;
+
+ /* need to make a copy of the docstring slot_, which usually
+ points to a static string literal */
+ if (slot_->slot_ == Py_tp_doc) {
+ // No signature in Python 2
+ // const char *old_doc = _PyType_DocWithoutSignature(type->tp_name, slot_->pfunc);
+ const char *old_doc = (const char *)slot_->pfunc;
+ size_t len = strlen(old_doc)+1;
+ char *tp_doc = (char *)PyObject_MALLOC(len); // C++11
+ if (tp_doc == NULL) {
+ PyErr_NoMemory();
+ goto fail;
+ }
+ memcpy(tp_doc, old_doc, len);
+ type->tp_doc = tp_doc;
+ }
+ }
+ if (type->tp_dealloc == NULL) {
+ /* It's a heap type, so needs the heap types' dealloc.
+ subtype_dealloc will call the base type's tp_dealloc, if
+ necessary. */
+ type->tp_dealloc = subtype_dealloc;
+ }
+
+ if (PyType_Ready(type) < 0)
+ goto fail;
+
+ // no ht_hached_keys in Python 2
+ // if (type->tp_dictoffset) {
+ // res->ht_cached_keys = _PyDict_NewKeysForClass();
+ // }
+
+ /* Set type.__module__ */
+ s = (char *)strrchr(spec->name, '.'); // c++11
+ if (s != NULL) {
+ int err;
+ // was PyUnicode_FromStringAndSize in Python 3
+ modname = PyString_FromStringAndSize(
+ spec->name, (Py_ssize_t)(s - spec->name));
+ if (modname == NULL) {
+ goto fail;
+ }
+ // no PyId_ things in Python 2
+ // err = _PyDict_SetItemId(type->tp_dict, &PyId___module__, modname);
+ err = PyDict_SetItemString(type->tp_dict, "__module__", modname);
+ Py_DECREF(modname);
+ if (err != 0)
+ goto fail;
+ } else {
+ // no PyErr_WarnFormat in Python 2
+ // if (PyErr_WarnFormat(PyExc_DeprecationWarning, 1,
+ // "builtin type %.200s has no __module__ attribute",
+ // spec->name))
+ char msg[250];
+ sprintf(msg, "builtin type %.200s has no __module__ attribute", spec->name);
+ if (PyErr_WarnEx(PyExc_DeprecationWarning, msg, 1))
+ goto fail;
+ }
+
+ return (PyObject*)res;
+
+ fail:
+ Py_DECREF(res);
+ return NULL;
+}
+
+PyObject *
+PyType_FromSpec(PyType_Spec *spec)
+{
+ return PyType_FromSpecWithBases(spec, NULL);
+}
+
+void *
+PyType_GetSlot(PyTypeObject *type, int slot_)
+{
+ if (!PyType_HasFeature(type, Py_TPFLAGS_HEAPTYPE) || slot_ < 0) {
+ PyErr_BadInternalCall();
+ return NULL;
+ }
+ if ((size_t)slot_ >= Py_ARRAY_LENGTH(slotoffsets)) {
+ /* Extension module requesting slot_ from a future version */
+ return NULL;
+ }
+ return *(void**)(((char*)type) + slotoffsets[slot_]);
+}
+
+} // extern "C"
+#endif // PY_MAJOR_VERSION < 3
diff --git a/sources/shiboken2/libshiboken/typespec.h b/sources/shiboken2/libshiboken/typespec.h
new file mode 100644
index 00000000..799fcb1b
--- /dev/null
+++ b/sources/shiboken2/libshiboken/typespec.h
@@ -0,0 +1,153 @@
+/****************************************************************************
+**
+** Copyright (C) 2018 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of Qt for Python.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 3 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL3 included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 3 requirements
+** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 2.0 or (at your option) the GNU General
+** Public license version 3 or any later version approved by the KDE Free
+** Qt Foundation. The licenses are as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-2.0.html and
+** https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef TYPESPEC_H
+#define TYPESPEC_H
+
+#include <Python.h>
+#include "shibokenmacros.h"
+
+#if PY_MAJOR_VERSION < 3
+extern "C"
+{
+
+typedef struct{
+ int slot_; // slot is somehow reserved in Qt /* slot id, see below */
+ void *pfunc; /* function pointer */
+} PyType_Slot;
+
+typedef struct{
+ const char* name;
+ int basicsize;
+ int itemsize;
+ unsigned int flags;
+ PyType_Slot *slots; /* terminated by slot==0. */
+} PyType_Spec;
+
+LIBSHIBOKEN_API PyObject *PyType_FromSpec(PyType_Spec*);
+#if !defined(Py_LIMITED_API) || Py_LIMITED_API+0 >= 0x03030000
+LIBSHIBOKEN_API PyObject *PyType_FromSpecWithBases(PyType_Spec*, PyObject*);
+#endif
+#if !defined(Py_LIMITED_API) || Py_LIMITED_API+0 >= 0x03040000
+LIBSHIBOKEN_API void* PyType_GetSlot(PyTypeObject*, int);
+#endif
+
+// from typeslots.h
+/* Do not renumber the file; these numbers are part of the stable ABI. */
+/* Disabled, see #10181 */
+#undef Py_bf_getbuffer
+#undef Py_bf_releasebuffer
+#define Py_mp_ass_subscript 3
+#define Py_mp_length 4
+#define Py_mp_subscript 5
+#define Py_nb_absolute 6
+#define Py_nb_add 7
+#define Py_nb_and 8
+#define Py_nb_nonzero 9
+#define Py_nb_divmod 10
+#define Py_nb_float 11
+#define Py_nb_floor_divide 12
+#define Py_nb_index 13
+#define Py_nb_inplace_add 14
+#define Py_nb_inplace_and 15
+#define Py_nb_inplace_floor_divide 16
+#define Py_nb_inplace_lshift 17
+#define Py_nb_inplace_multiply 18
+#define Py_nb_inplace_or 19
+#define Py_nb_inplace_power 20
+#define Py_nb_inplace_remainder 21
+#define Py_nb_inplace_rshift 22
+#define Py_nb_inplace_subtract 23
+#define Py_nb_inplace_true_divide 24
+#define Py_nb_inplace_xor 25
+#define Py_nb_int 26
+#define Py_nb_invert 27
+#define Py_nb_lshift 28
+#define Py_nb_multiply 29
+#define Py_nb_negative 30
+#define Py_nb_or 31
+#define Py_nb_positive 32
+#define Py_nb_power 33
+#define Py_nb_remainder 34
+#define Py_nb_rshift 35
+#define Py_nb_subtract 36
+#define Py_nb_true_divide 37
+#define Py_nb_xor 38
+#define Py_sq_ass_item 39
+#define Py_sq_concat 40
+#define Py_sq_contains 41
+#define Py_sq_inplace_concat 42
+#define Py_sq_inplace_repeat 43
+#define Py_sq_item 44
+#define Py_sq_length 45
+#define Py_sq_repeat 46
+#define Py_tp_alloc 47
+#define Py_tp_base 48
+#define Py_tp_bases 49
+#define Py_tp_call 50
+#define Py_tp_clear 51
+#define Py_tp_dealloc 52
+#define Py_tp_del 53
+#define Py_tp_descr_get 54
+#define Py_tp_descr_set 55
+#define Py_tp_doc 56
+#define Py_tp_getattr 57
+#define Py_tp_getattro 58
+#define Py_tp_hash 59
+#define Py_tp_init 60
+#define Py_tp_is_gc 61
+#define Py_tp_iter 62
+#define Py_tp_iternext 63
+#define Py_tp_methods 64
+#define Py_tp_new 65
+#define Py_tp_repr 66
+#define Py_tp_richcompare 67
+#define Py_tp_setattr 68
+#define Py_tp_setattro 69
+#define Py_tp_str 70
+#define Py_tp_traverse 71
+#define Py_tp_members 72
+#define Py_tp_getset 73
+#define Py_tp_free 74
+#define Py_nb_long 75
+#define Py_nb_divide 76
+#define Py_sq_slice 77
+} // extern "C"
+#endif // PY_MAJOR_VERSION < 3
+#endif // TYPESPEC_H
diff --git a/sources/shiboken2/libshiboken/voidptr.cpp b/sources/shiboken2/libshiboken/voidptr.cpp
index 79029759..afb3f404 100644
--- a/sources/shiboken2/libshiboken/voidptr.cpp
+++ b/sources/shiboken2/libshiboken/voidptr.cpp
@@ -55,7 +55,8 @@ typedef struct {
PyObject *SbkVoidPtrObject_new(PyTypeObject *type, PyObject *args, PyObject *kwds)
{
- SbkVoidPtrObject *self = reinterpret_cast<SbkVoidPtrObject *>(type->tp_alloc(type, 0));
+ SbkVoidPtrObject *self =
+ reinterpret_cast<SbkVoidPtrObject *>(PepType(type)->tp_alloc);
if (self != 0) {
self->cptr = 0;
@@ -66,7 +67,7 @@ PyObject *SbkVoidPtrObject_new(PyTypeObject *type, PyObject *args, PyObject *kwd
return reinterpret_cast<PyObject *>(self);
}
-#define SbkVoidPtr_Check(op) (Py_TYPE(op) == &SbkVoidPtrType)
+#define SbkVoidPtr_Check(op) (Py_TYPE(op) == SbkVoidPtrTypeF())
int SbkVoidPtrObject_init(PyObject *self, PyObject *args, PyObject *kwds)
@@ -168,62 +169,6 @@ PyObject *SbkVoidPtrObject_int(PyObject *v)
return PyLong_FromVoidPtr(sbkObject->cptr);
}
-static PyNumberMethods SbkVoidPtrObjectAsNumber = {
- /* nb_add */ 0,
- /* nb_subtract */ 0,
- /* nb_multiply */ 0,
-#ifndef IS_PY3K
- /* nb_divide */ 0,
-#endif
- /* nb_remainder */ 0,
- /* nb_divmod */ 0,
- /* nb_power */ 0,
- /* nb_negative */ 0,
- /* nb_positive */ 0,
- /* nb_absolute */ 0,
- /* nb_bool/nb_nonzero */ 0,
- /* nb_invert */ 0,
- /* nb_lshift */ 0,
- /* nb_rshift */ 0,
- /* nb_and */ 0,
- /* nb_xor */ 0,
- /* nb_or */ 0,
-#ifndef IS_PY3K
- /* nb_coerce */ 0,
-#endif
- /* nb_int */ SbkVoidPtrObject_int,
-#ifdef IS_PY3K
- /* nb_reserved */ 0,
- /* nb_float */ 0,
-#else
- /* nb_long */ 0,
- /* 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 */ 0
-};
-
static Py_ssize_t SbkVoidPtrObject_length(PyObject *v)
{
SbkVoidPtrObject *sbkObject = reinterpret_cast<SbkVoidPtrObject *>(v);
@@ -235,19 +180,6 @@ static Py_ssize_t SbkVoidPtrObject_length(PyObject *v)
return sbkObject->size;
}
-static PySequenceMethods SbkVoidPtrObjectAsSequence = {
- /* sq_length */ SbkVoidPtrObject_length,
- /* sq_concat */ 0,
- /* sq_repeat */ 0,
- /* sq_item */ 0,
- /* sq_slice */ 0,
- /* sq_ass_item */ 0,
- /* sq_ass_slice */ 0,
- /* sq_contains */ 0,
- /* sq_inplace_concat */ 0,
- /* sq_inplace_repeat */ 0
-};
-
static const char trueString[] = "True" ;
static const char falseString[] = "False" ;
@@ -257,7 +189,7 @@ PyObject *SbkVoidPtrObject_repr(PyObject *v)
SbkVoidPtrObject *sbkObject = reinterpret_cast<SbkVoidPtrObject *>(v);
PyObject *s = PyBytes_FromFormat("%s(%p, %zd, %s)",
- Py_TYPE(sbkObject)->tp_name,
+ PepType((Py_TYPE(sbkObject)))->tp_name,
sbkObject->cptr,
sbkObject->size,
sbkObject->isWritable ? trueString : falseString);
@@ -269,7 +201,7 @@ PyObject *SbkVoidPtrObject_str(PyObject *v)
{
SbkVoidPtrObject *sbkObject = reinterpret_cast<SbkVoidPtrObject *>(v);
PyObject *s = PyBytes_FromFormat("%s(Address %p, Size %zd, isWritable %s)",
- Py_TYPE(sbkObject)->tp_name,
+ PepType((Py_TYPE(sbkObject)))->tp_name,
sbkObject->cptr,
sbkObject->size,
sbkObject->isWritable ? trueString : falseString);
@@ -279,61 +211,35 @@ PyObject *SbkVoidPtrObject_str(PyObject *v)
// Void pointer type definition.
-PyTypeObject SbkVoidPtrType = {
- PyVarObject_HEAD_INIT(&PyType_Type, 0) /*ob_size*/
- "VoidPtr", /*tp_name*/
- sizeof(SbkVoidPtrObject), /*tp_basicsize*/
- 0, /*tp_itemsize*/
- 0, /*tp_dealloc*/
- 0, /*tp_print*/
- 0, /*tp_getattr*/
- 0, /*tp_setattr*/
- 0, /*tp_compare*/
- SbkVoidPtrObject_repr, /*tp_repr*/
- &SbkVoidPtrObjectAsNumber, /*tp_as_number*/
- &SbkVoidPtrObjectAsSequence, /*tp_as_sequence*/
- 0, /*tp_as_mapping*/
- 0, /*tp_hash */
- 0, /*tp_call*/
- SbkVoidPtrObject_str, /*tp_str*/
- 0, /*tp_getattro*/
- 0, /*tp_setattro*/
- 0, /*tp_as_buffer*/
- Py_TPFLAGS_DEFAULT, /*tp_flags*/
- "Void pointer wrapper", /*tp_doc*/
- 0, /*tp_traverse*/
- 0, /*tp_clear*/
- SbkVoidPtrObject_richcmp, /*tp_richcompare*/
- 0, /*tp_weaklistoffset*/
- 0, /*tp_iter*/
- 0, /*tp_iternext*/
- 0, /*tp_methods*/
- 0, /*tp_members*/
- 0, /*tp_getset*/
- 0, /*tp_base*/
- 0, /*tp_dict*/
- 0, /*tp_descr_get*/
- 0, /*tp_descr_set*/
- 0, /*tp_dictoffset*/
- SbkVoidPtrObject_init, /*tp_init*/
- 0, /*tp_alloc*/
- SbkVoidPtrObject_new, /*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*/
-#if PY_MAJOR_VERSION > 3 || PY_MAJOR_VERSION == 3 && PY_MINOR_VERSION >= 4
- 0 /*tp_finalize*/
-#endif
+static PyType_Slot SbkVoidPtrType_slots[] = {
+ {Py_tp_repr, (void *)SbkVoidPtrObject_repr},
+ {Py_nb_int, (void *)SbkVoidPtrObject_int},
+ {Py_sq_length, (void *)SbkVoidPtrObject_length},
+ {Py_tp_str, (void *)SbkVoidPtrObject_str},
+ {Py_tp_richcompare, (void *)SbkVoidPtrObject_richcmp},
+ {Py_tp_init, (void *)SbkVoidPtrObject_init},
+ {Py_tp_new, (void *)SbkVoidPtrObject_new},
+ {Py_tp_dealloc, (void *)SbkDummyDealloc},
+ {0, 0}
};
+static PyType_Spec SbkVoidPtrType_spec = {
+ "shiboken2.libshiboken.VoidPtr",
+ sizeof(SbkVoidPtrObject),
+ 0,
+ Py_TPFLAGS_DEFAULT,
+ SbkVoidPtrType_slots,
+};
+
}
+PyTypeObject *SbkVoidPtrTypeF(void)
+{
+ static PyTypeObject *type = nullptr;
+ if (!type)
+ type = (PyTypeObject *)PyType_FromSpec(&SbkVoidPtrType_spec);
+ return type;
+}
namespace VoidPtr {
@@ -341,7 +247,7 @@ static int voidPointerInitialized = false;
void init()
{
- if (PyType_Ready(reinterpret_cast<PyTypeObject *>(&SbkVoidPtrType)) < 0)
+ if (PyType_Ready(reinterpret_cast<PyTypeObject *>(SbkVoidPtrTypeF())) < 0)
Py_FatalError("[libshiboken] Failed to initialize Shiboken.VoidPtr type.");
else
voidPointerInitialized = true;
@@ -350,9 +256,9 @@ void init()
void addVoidPtrToModule(PyObject *module)
{
if (voidPointerInitialized) {
- Py_INCREF(&SbkVoidPtrType);
- PyModule_AddObject(module, SbkVoidPtrType.tp_name,
- reinterpret_cast<PyObject *>(&SbkVoidPtrType));
+ Py_INCREF(SbkVoidPtrTypeF());
+ PyModule_AddObject(module, PepType_GetNameStr(SbkVoidPtrTypeF()),
+ reinterpret_cast<PyObject *>(SbkVoidPtrTypeF()));
}
}
@@ -361,7 +267,7 @@ static PyObject *createVoidPtr(void *cppIn, Py_ssize_t size = 0, bool isWritable
if (!cppIn)
Py_RETURN_NONE;
- SbkVoidPtrObject *result = PyObject_NEW(SbkVoidPtrObject, &SbkVoidPtrType);
+ SbkVoidPtrObject *result = PyObject_New(SbkVoidPtrObject, SbkVoidPtrTypeF());
if (!result)
Py_RETURN_NONE;
@@ -434,7 +340,7 @@ static PythonToCppFunc PythonBufferToCppIsConvertible(PyObject *pyIn)
SbkConverter *createConverter()
{
- SbkConverter *converter = Shiboken::Conversions::createConverter(&SbkVoidPtrType, toPython);
+ SbkConverter *converter = Shiboken::Conversions::createConverter(SbkVoidPtrTypeF(), toPython);
Shiboken::Conversions::addPythonToCppValueConversion(converter,
VoidPtrToCpp,
VoidPtrToCppIsConvertible);
diff --git a/sources/shiboken2/libshiboken/voidptr.h b/sources/shiboken2/libshiboken/voidptr.h
index 240895df..e74c1045 100644
--- a/sources/shiboken2/libshiboken/voidptr.h
+++ b/sources/shiboken2/libshiboken/voidptr.h
@@ -40,7 +40,7 @@
#ifndef VOIDPTR_H
#define VOIDPTR_H
-#include <Python.h>
+#include "sbkpython.h"
#include "shibokenmacros.h"
#include "sbkconverter.h"
@@ -48,7 +48,7 @@ extern "C"
{
// Void pointer type declaration.
-extern LIBSHIBOKEN_API PyTypeObject SbkVoidPtrType;
+extern LIBSHIBOKEN_API PyTypeObject *SbkVoidPtrTypeF(void);
} // extern "C"
diff --git a/sources/shiboken2/tests/minimalbinding/CMakeLists.txt b/sources/shiboken2/tests/minimalbinding/CMakeLists.txt
index 7edb0290..b8b6417d 100644
--- a/sources/shiboken2/tests/minimalbinding/CMakeLists.txt
+++ b/sources/shiboken2/tests/minimalbinding/CMakeLists.txt
@@ -26,7 +26,8 @@ include_directories(${CMAKE_CURRENT_SOURCE_DIR}
${CMAKE_SOURCE_DIR}
${SBK_PYTHON_INCLUDE_DIR}
${libminimal_SOURCE_DIR}
- ${libshiboken_SOURCE_DIR})
+ ${libshiboken_SOURCE_DIR}
+ ${libshiboken_BINARY_DIR})
add_library(minimal MODULE ${minimal_SRC})
set_property(TARGET minimal PROPERTY PREFIX "")
set_property(TARGET minimal PROPERTY OUTPUT_NAME "minimal${PYTHON_EXTENSION_SUFFIX}")
diff --git a/sources/shiboken2/tests/otherbinding/CMakeLists.txt b/sources/shiboken2/tests/otherbinding/CMakeLists.txt
index 7d4dd5b5..186766b4 100644
--- a/sources/shiboken2/tests/otherbinding/CMakeLists.txt
+++ b/sources/shiboken2/tests/otherbinding/CMakeLists.txt
@@ -32,7 +32,8 @@ include_directories(${CMAKE_CURRENT_SOURCE_DIR}
${libsample_SOURCE_DIR}/..
${sample_BINARY_DIR}
${sample_BINARY_DIR}/sample
- ${libshiboken_SOURCE_DIR})
+ ${libshiboken_SOURCE_DIR}
+ ${libshiboken_BINARY_DIR})
add_library(other MODULE ${other_SRC})
set_property(TARGET other PROPERTY PREFIX "")
set_property(TARGET other PROPERTY OUTPUT_NAME "other${PYTHON_EXTENSION_SUFFIX}")
diff --git a/sources/shiboken2/tests/samplebinding/CMakeLists.txt b/sources/shiboken2/tests/samplebinding/CMakeLists.txt
index 78ddfca0..32117e44 100644
--- a/sources/shiboken2/tests/samplebinding/CMakeLists.txt
+++ b/sources/shiboken2/tests/samplebinding/CMakeLists.txt
@@ -136,7 +136,8 @@ include_directories(${CMAKE_CURRENT_SOURCE_DIR}
${CMAKE_SOURCE_DIR}
${SBK_PYTHON_INCLUDE_DIR}
${libsample_SOURCE_DIR}
- ${libshiboken_SOURCE_DIR})
+ ${libshiboken_SOURCE_DIR}
+ ${libshiboken_BINARY_DIR})
add_library(sample MODULE ${sample_SRC})
set_property(TARGET sample PROPERTY PREFIX "")
set_property(TARGET sample PROPERTY OUTPUT_NAME "sample${PYTHON_EXTENSION_SUFFIX}")
diff --git a/sources/shiboken2/tests/samplebinding/bytearray_bufferprotocol.cpp b/sources/shiboken2/tests/samplebinding/bytearray_bufferprotocol.cpp
index 8f01b4a0..32238708 100644
--- a/sources/shiboken2/tests/samplebinding/bytearray_bufferprotocol.cpp
+++ b/sources/shiboken2/tests/samplebinding/bytearray_bufferprotocol.cpp
@@ -33,7 +33,7 @@ extern "C" {
static Py_ssize_t SbkByteArray_segcountproc(PyObject* self, Py_ssize_t* lenp)
{
if (lenp)
- *lenp = self->ob_type->tp_as_sequence->sq_length(self);
+ *lenp = Py_TYPE(self)->tp_as_sequence->sq_length(self);
return 1;
}
static Py_ssize_t SbkByteArray_readbufferproc(PyObject* self, Py_ssize_t segment, void** ptrptr)
diff --git a/sources/shiboken2/tests/samplebinding/namespace_test.py b/sources/shiboken2/tests/samplebinding/namespace_test.py
index a5065c7a..5fcdab97 100644
--- a/sources/shiboken2/tests/samplebinding/namespace_test.py
+++ b/sources/shiboken2/tests/samplebinding/namespace_test.py
@@ -33,12 +33,7 @@
import unittest
from sample import *
-from py3kcompat import IS_PY3K
-if IS_PY3K:
- TYPE_STR = "class"
-else:
- TYPE_STR = "type"
class TestEnumUnderNamespace(unittest.TestCase):
def testInvisibleNamespace(self):
@@ -59,11 +54,16 @@ class TestClassesUnderNamespace(unittest.TestCase):
self.assertEqual(res, 4)
def testTpNames(self):
- self.assertEqual(str(SampleNamespace.SomeClass), "<%s 'sample.SampleNamespace.SomeClass'>"%TYPE_STR)
- self.assertEqual(str(SampleNamespace.SomeClass.ProtectedEnum), "<%s 'sample.SampleNamespace.SomeClass.ProtectedEnum'>"%TYPE_STR)
- self.assertEqual(str(SampleNamespace.SomeClass.SomeInnerClass.ProtectedEnum), "<%s 'sample.SampleNamespace.SomeClass.SomeInnerClass.ProtectedEnum'>"%TYPE_STR)
- self.assertEqual(str(SampleNamespace.SomeClass.SomeInnerClass.OkThisIsRecursiveEnough), "<%s 'sample.SampleNamespace.SomeClass.SomeInnerClass.OkThisIsRecursiveEnough'>"%TYPE_STR)
- self.assertEqual(str(SampleNamespace.SomeClass.SomeInnerClass.OkThisIsRecursiveEnough.NiceEnum), "<%s 'sample.SampleNamespace.SomeClass.SomeInnerClass.OkThisIsRecursiveEnough.NiceEnum'>"%TYPE_STR)
+ self.assertEqual(str(SampleNamespace.SomeClass),
+ "<class 'sample.SampleNamespace.SomeClass'>")
+ self.assertEqual(str(SampleNamespace.SomeClass.ProtectedEnum),
+ "<class 'sample.SampleNamespace.SomeClass.ProtectedEnum'>")
+ self.assertEqual(str(SampleNamespace.SomeClass.SomeInnerClass.ProtectedEnum),
+ "<class 'sample.SampleNamespace.SomeClass.SomeInnerClass.ProtectedEnum'>")
+ self.assertEqual(str(SampleNamespace.SomeClass.SomeInnerClass.OkThisIsRecursiveEnough),
+ "<class 'sample.SampleNamespace.SomeClass.SomeInnerClass.OkThisIsRecursiveEnough'>")
+ self.assertEqual(str(SampleNamespace.SomeClass.SomeInnerClass.OkThisIsRecursiveEnough.NiceEnum),
+ "<class 'sample.SampleNamespace.SomeClass.SomeInnerClass.OkThisIsRecursiveEnough.NiceEnum'>")
if __name__ == '__main__':
unittest.main()
diff --git a/sources/shiboken2/tests/samplebinding/typesystem_sample.xml b/sources/shiboken2/tests/samplebinding/typesystem_sample.xml
index 3cc80860..5f0a9206 100644
--- a/sources/shiboken2/tests/samplebinding/typesystem_sample.xml
+++ b/sources/shiboken2/tests/samplebinding/typesystem_sample.xml
@@ -1666,7 +1666,7 @@
Tested in InjectCodeTest.testTypeNativeBeginning_TypeTargetBeginning:
-->
<inject-code class="target" position="beginning">
- %PYTHONTYPEOBJECT.tp_str = InjectCode_tpstr;
+ PepType(&amp;%PYTHONTYPEOBJECT)->tp_str = InjectCode_tpstr;
</inject-code>
<!-- Tested in InjectCodeTest.testFunctionTargetBeginning_FunctionTargetEnd -->
@@ -2178,7 +2178,7 @@
</add-function>
<add-function signature="__repr__" return-type="PyObject*">
<inject-code class="target" position="beginning">
- ByteArray b(((PyObject*)%PYSELF)->ob_type->tp_name);
+ ByteArray b(PepType(Py_TYPE(%PYSELF))->tp_name);
PyObject* aux = Shiboken::String::fromStringAndSize(%CPPSELF.data(), %CPPSELF.size());
if (PyUnicode_CheckExact(aux)) {
PyObject* tmp = PyUnicode_AsASCIIString(aux);
diff --git a/sources/shiboken2/tests/smartbinding/CMakeLists.txt b/sources/shiboken2/tests/smartbinding/CMakeLists.txt
index aab2121d..faaa797b 100644
--- a/sources/shiboken2/tests/smartbinding/CMakeLists.txt
+++ b/sources/shiboken2/tests/smartbinding/CMakeLists.txt
@@ -27,7 +27,8 @@ include_directories(${CMAKE_CURRENT_SOURCE_DIR}
${CMAKE_SOURCE_DIR}
${SBK_PYTHON_INCLUDE_DIR}
${libsmart_SOURCE_DIR}
- ${libshiboken_SOURCE_DIR})
+ ${libshiboken_SOURCE_DIR}
+ ${libshiboken_BINARY_DIR})
add_library(smart MODULE ${smart_SRC})
set_property(TARGET smart PROPERTY PREFIX "")
set_property(TARGET smart PROPERTY OUTPUT_NAME "smart${PYTHON_EXTENSION_SUFFIX}")