aboutsummaryrefslogtreecommitdiffstats
path: root/sources/shiboken2/libshiboken/basewrapper.cpp
diff options
context:
space:
mode:
authorChristian Tismer <tismer@stackless.com>2017-12-17 19:12:56 +0100
committerAlexandru Croitor <alexandru.croitor@qt.io>2018-05-30 18:13:41 +0000
commit18dc31becdd994c53a9f894087cf1ef99fbd0232 (patch)
tree3021cfa473f20102bfb63a26117776615b91b526 /sources/shiboken2/libshiboken/basewrapper.cpp
parent50dd4ae202d7afb3556335c056db003f5ef50532 (diff)
PEP 384-squash: Implement PEP 384
This is the condensed checkin of 18 commits which created the implementation of PEP 384. Task-number: PYSIDE-560 Change-Id: I834c659af4c2b55b268f8e8dc4cfa53f02502409 Reviewed-by: Qt CI Bot <qt_ci_bot@qt-project.org> Reviewed-by: Alexandru Croitor <alexandru.croitor@qt.io>
Diffstat (limited to 'sources/shiboken2/libshiboken/basewrapper.cpp')
-rw-r--r--sources/shiboken2/libshiboken/basewrapper.cpp500
1 files changed, 259 insertions, 241 deletions
diff --git a/sources/shiboken2/libshiboken/basewrapper.cpp b/sources/shiboken2/libshiboken/basewrapper.cpp
index 21f6933d2..0e2712ec8 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 {