aboutsummaryrefslogtreecommitdiffstats
path: root/sources/shiboken2/libshiboken
diff options
context:
space:
mode:
Diffstat (limited to 'sources/shiboken2/libshiboken')
-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
28 files changed, 3738 insertions, 658 deletions
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"