1 /****************************************************************************
2 **
3 ** Copyright (C) 2019 The Qt Company Ltd.
4 ** Contact: https://www.qt.io/licensing/
5 **
6 ** This file is part of Qt for Python.
7 **
8 ** $QT_BEGIN_LICENSE:LGPL$
9 ** Commercial License Usage
10 ** Licensees holding valid commercial Qt licenses may use this file in
11 ** accordance with the commercial license agreement provided with the
12 ** Software or, alternatively, in accordance with the terms contained in
13 ** a written agreement between you and The Qt Company. For licensing terms
14 ** and conditions see https://www.qt.io/terms-conditions. For further
15 ** information use the contact form at https://www.qt.io/contact-us.
16 **
17 ** GNU Lesser General Public License Usage
18 ** Alternatively, this file may be used under the terms of the GNU Lesser
19 ** General Public License version 3 as published by the Free Software
20 ** Foundation and appearing in the file LICENSE.LGPL3 included in the
21 ** packaging of this file. Please review the following information to
22 ** ensure the GNU Lesser General Public License version 3 requirements
23 ** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
24 **
25 ** GNU General Public License Usage
26 ** Alternatively, this file may be used under the terms of the GNU
27 ** General Public License version 2.0 or (at your option) the GNU General
28 ** Public license version 3 or any later version approved by the KDE Free
29 ** Qt Foundation. The licenses are as published by the Free Software
30 ** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
31 ** included in the packaging of this file. Please review the following
32 ** information to ensure the GNU General Public License requirements will
33 ** be met: https://www.gnu.org/licenses/gpl-2.0.html and
34 ** https://www.gnu.org/licenses/gpl-3.0.html.
35 **
36 ** $QT_END_LICENSE$
37 **
38 ****************************************************************************/
39 
40 #include "basewrapper.h"
41 #include "basewrapper_p.h"
42 #include "bindingmanager.h"
43 #include "helper.h"
44 #include "sbkconverter.h"
45 #include "sbkenum.h"
46 #include "sbkstring.h"
47 #include "sbkstaticstrings.h"
48 #include "sbkstaticstrings_p.h"
49 #include "autodecref.h"
50 #include "gilstate.h"
51 #include <string>
52 #include <cstring>
53 #include <cstddef>
54 #include <set>
55 #include <sstream>
56 #include <algorithm>
57 #include "threadstatesaver.h"
58 #include "signature.h"
59 #include "qapp_macro.h"
60 #include "voidptr.h"
61 
62 #include <iostream>
63 
64 #if defined(__APPLE__)
65 #include <dlfcn.h>
66 #endif
67 
68 namespace {
69     void _destroyParentInfo(SbkObject *obj, bool keepReference);
70 }
71 
callDestructor(const Shiboken::DtorAccumulatorVisitor::DestructorEntries & dts)72 static void callDestructor(const Shiboken::DtorAccumulatorVisitor::DestructorEntries &dts)
73 {
74     for (const auto &e : dts) {
75         Shiboken::ThreadStateSaver threadSaver;
76         threadSaver.save();
77         e.destructor(e.cppInstance);
78     }
79 }
80 
81 extern "C"
82 {
83 
84 // PYSIDE-939: A general replacement for object_dealloc.
Sbk_object_dealloc(PyObject * self)85 void Sbk_object_dealloc(PyObject *self)
86 {
87     if (PepRuntime_38_flag) {
88         // PYSIDE-939: Handling references correctly.
89         // This was not needed before Python 3.8 (Python issue 35810)
90         Py_DECREF(Py_TYPE(self));
91     }
92     Py_TYPE(self)->tp_free(self);
93 }
94 
95 static void SbkObjectTypeDealloc(PyObject *pyObj);
96 static PyObject *SbkObjectTypeTpNew(PyTypeObject *metatype, PyObject *args, PyObject *kwds);
97 
98 static SelectableFeatureHook SelectFeatureSet = nullptr;
99 
100 static PyObject *Sbk_TypeGet___dict__(PyTypeObject *type, void *context);   // forward
101 
102 static int
check_set_special_type_attr(PyTypeObject * type,PyObject * value,const char * name)103 check_set_special_type_attr(PyTypeObject *type, PyObject *value, const char *name)
104 {
105     if (!(type->tp_flags & Py_TPFLAGS_HEAPTYPE)) {
106         PyErr_Format(PyExc_TypeError,
107                      "can't set %s.%s", type->tp_name, name);
108         return 0;
109     }
110     if (!value) {
111         PyErr_Format(PyExc_TypeError,
112                      "can't delete %s.%s", type->tp_name, name);
113         return 0;
114     }
115     return 1;
116 }
117 
118 // PYSIDE-1177: Add a setter to allow setting type doc.
119 static int
type_set_doc(PyTypeObject * type,PyObject * value,void * context)120 type_set_doc(PyTypeObject *type, PyObject *value, void *context)
121 {
122     if (!check_set_special_type_attr(type, value, "__doc__"))
123         return -1;
124     PyType_Modified(type);
125     return PyDict_SetItem(type->tp_dict, Shiboken::PyMagicName::doc(), value);
126 }
127 
128 // PYSIDE-908: The function PyType_Modified does not work in PySide, so we need to
129 // explicitly pass __doc__. For __signature__ it _did_ actually work, because
130 // it was not existing before. We add them both for clarity.
131 static PyGetSetDef SbkObjectType_Type_getsetlist[] = {
132     {const_cast<char *>("__signature__"), (getter)Sbk_TypeGet___signature__},
133     {const_cast<char *>("__doc__"),       (getter)Sbk_TypeGet___doc__, (setter)type_set_doc},
134     {const_cast<char *>("__dict__"),      (getter)Sbk_TypeGet___dict__},
135     {nullptr}  // Sentinel
136 };
137 
138 #if PY_VERSION_HEX < 0x03000000
139 
SbkObjectType_repr(PyObject * type)140 static PyObject *SbkObjectType_repr(PyObject *type)
141 {
142     Shiboken::AutoDecRef mod(PyObject_GetAttr(type, Shiboken::PyMagicName::module()));
143     if (mod.isNull())
144         return nullptr;
145     Shiboken::AutoDecRef name(PyObject_GetAttr(type, Shiboken::PyMagicName::qualname()));
146     if (name.isNull())
147         return nullptr;
148     return PyString_FromFormat("<class '%s.%s'>",
149                                PyString_AS_STRING(mod.object()),
150                                PyString_AS_STRING(name.object()));
151 }
152 
153 #endif // PY_VERSION_HEX < 0x03000000
154 
155 static PyObject *(*type_getattro)(PyObject *type, PyObject *name);          // forward
156 static PyObject *mangled_type_getattro(PyTypeObject *type, PyObject *name); // forward
157 
158 static PyType_Slot SbkObjectType_Type_slots[] = {
159     {Py_tp_dealloc, reinterpret_cast<void *>(SbkObjectTypeDealloc)},
160     {Py_tp_getattro, reinterpret_cast<void *>(mangled_type_getattro)},
161     {Py_tp_base, static_cast<void *>(&PyType_Type)},
162     {Py_tp_alloc, reinterpret_cast<void *>(PyType_GenericAlloc)},
163     {Py_tp_new, reinterpret_cast<void *>(SbkObjectTypeTpNew)},
164     {Py_tp_free, reinterpret_cast<void *>(PyObject_GC_Del)},
165     {Py_tp_getset, reinterpret_cast<void *>(SbkObjectType_Type_getsetlist)},
166 #if PY_VERSION_HEX < 0x03000000
167     {Py_tp_repr, reinterpret_cast<void *>(SbkObjectType_repr)},
168 #endif
169     {0, nullptr}
170 };
171 static PyType_Spec SbkObjectType_Type_spec = {
172     "1:Shiboken.ObjectType",
173     0,   // basicsize (inserted later)
174     sizeof(PyMemberDef),
175     Py_TPFLAGS_DEFAULT|Py_TPFLAGS_BASETYPE,
176     SbkObjectType_Type_slots,
177 };
178 
179 
180 #if PY_VERSION_HEX < 0x03000000
181 /*****************************************************************************
182  *
183  * PYSIDE-816: Workaround for Python 2.7 for SbkObjectType_TypeF().
184  *
185  * This is an add-on for function typeobject.c:tp_new_wrapper from Python 2.7 .
186  * Problem:
187  * In Python 3.X, tp_new_wrapper uses this check:
188 
189     while (staticbase && (staticbase->tp_new == slot_tp_new))
190 
191  * In Python 2.7, it uses this, instead:
192 
193     while (staticbase && (staticbase->tp_flags & Py_TPFLAGS_HEAPTYPE))
194 
195  * The problem is that heap types have this unwanted dependency.
196  * But we cannot get at static slot_tp_new, and so we have to use
197  * the original function and patch Py_TPFLAGS_HEAPTYPE away during the call.
198  *
199  * PYSIDE-1051: The same problem holds for all dynamic metatypes generated by
200  *              SbkObjectTypeTpNew()   and all types generated by
201  *              introduceWrapperType() .
202  *
203  * This led to a drastic overhaul of patch_tp_new_wrapper() which now adds
204  * the new wrapper to exactly those types which have the old wrapper.
205  */
206 
207 ternaryfunc old_tp_new_wrapper = nullptr;
208 
209 static PyObject *
tp_new_wrapper(PyObject * self,PyObject * args,PyObject * kwds)210 tp_new_wrapper(PyObject *self, PyObject *args, PyObject *kwds)
211 {
212     PyTypeObject *type = reinterpret_cast<PyTypeObject *>(self);
213     Py_ssize_t orig_flags = type->tp_flags;
214     type->tp_flags &= ~Py_TPFLAGS_HEAPTYPE;
215     PyObject *ret = reinterpret_cast<ternaryfunc>(old_tp_new_wrapper)(self, args, kwds);
216     type->tp_flags = orig_flags;
217     return ret;
218 }
219 
220 // This is intentionally the __new__ docstring of Python 3.7 .
221 static struct PyMethodDef tp_new_methoddef[] = {
222     {"__new__", reinterpret_cast<PyCFunction>(tp_new_wrapper), METH_VARARGS|METH_KEYWORDS,
223      PyDoc_STR("__new__($type, *args, **kwargs)\n--\n\n"
224                "Create and return a new object.  "
225                "See help(type) for accurate signature.")},
226     {0}
227 };
228 
229 static int
patch_tp_new_wrapper(PyTypeObject * type)230 patch_tp_new_wrapper(PyTypeObject *type)
231 {
232     /*
233      * The old tp_new_wrapper is added to all types that have tp_new.
234      * We patch that with a version that ignores the heaptype flag.
235      */
236     auto newMethod = Shiboken::PyMagicName::new_();
237     if (old_tp_new_wrapper == nullptr) {
238         PyObject *func = PyDict_GetItem(PyType_Type.tp_dict, newMethod);
239         assert(func);
240         PyCFunctionObject *pycf_ob = reinterpret_cast<PyCFunctionObject *>(func);
241         old_tp_new_wrapper = reinterpret_cast<ternaryfunc>(pycf_ob->m_ml->ml_meth);
242     }
243     PyObject *mro = type->tp_mro;
244     Py_ssize_t i, n = PyTuple_GET_SIZE(mro);
245     for (i = 0; i < n; i++) {
246         type = reinterpret_cast<PyTypeObject *>(PyTuple_GET_ITEM(mro, i));
247         PyObject *existing = PyDict_GetItem(type->tp_dict, newMethod);
248         if (existing && PyCFunction_Check(existing)
249                      && type->tp_flags & Py_TPFLAGS_HEAPTYPE) {
250             auto *pycf_ob = reinterpret_cast<PyCFunctionObject *>(existing);
251             auto existing_wrapper = reinterpret_cast<ternaryfunc>(pycf_ob->m_ml->ml_meth);
252             if (existing_wrapper == tp_new_wrapper)
253                 break;
254             if (existing_wrapper == old_tp_new_wrapper) {
255                 PyObject *ob_type = reinterpret_cast<PyObject *>(type);
256                 Shiboken::AutoDecRef func(PyCFunction_New(tp_new_methoddef, ob_type));
257                 if (func.isNull() || PyDict_SetItem(type->tp_dict, newMethod, func))
258                     return -1;
259             }
260         }
261     }
262     return 0;
263 }
264 /*****************************************************************************/
265 #endif // PY_VERSION_HEX < 0x03000000
266 
267 
SbkObjectType_TypeF(void)268 PyTypeObject *SbkObjectType_TypeF(void)
269 {
270     static PyTypeObject *type = nullptr;
271     if (!type) {
272         // PYSIDE-1019: Insert the default tp_getattro explicitly here
273         //              so we can overwrite it a bit.
274         type_getattro = PyType_Type.tp_getattro;
275         SbkObjectType_Type_spec.basicsize =
276             PepHeapType_SIZE + sizeof(SbkObjectTypePrivate);
277         type = reinterpret_cast<PyTypeObject *>(SbkType_FromSpec(&SbkObjectType_Type_spec));
278 #if PY_VERSION_HEX < 0x03000000
279         if (patch_tp_new_wrapper(type) < 0)
280             return nullptr;
281 #endif
282     }
283     return type;
284 }
285 
SbkObjectGetDict(PyObject * pObj,void *)286 static PyObject *SbkObjectGetDict(PyObject *pObj, void *)
287 {
288     auto *obj = reinterpret_cast<SbkObject *>(pObj);
289     if (!obj->ob_dict)
290         obj->ob_dict = PyDict_New();
291     if (!obj->ob_dict)
292         return nullptr;
293     Py_INCREF(obj->ob_dict);
294     return obj->ob_dict;
295 }
296 
297 static PyGetSetDef SbkObjectGetSetList[] = {
298     {const_cast<char *>("__dict__"), SbkObjectGetDict, nullptr, nullptr, nullptr},
299     {nullptr, nullptr, nullptr, nullptr, nullptr} // Sentinel
300 };
301 
SbkObject_traverse(PyObject * self,visitproc visit,void * arg)302 static int SbkObject_traverse(PyObject *self, visitproc visit, void *arg)
303 {
304     auto *sbkSelf = reinterpret_cast<SbkObject *>(self);
305 
306     //Visit children
307     Shiboken::ParentInfo *pInfo = sbkSelf->d->parentInfo;
308     if (pInfo) {
309         for (SbkObject *c : pInfo->children)
310              Py_VISIT(c);
311     }
312 
313     //Visit refs
314     Shiboken::RefCountMap *rInfo = sbkSelf->d->referredObjects;
315     if (rInfo) {
316         for (auto it = rInfo->begin(), end = rInfo->end(); it != end; ++it)
317             Py_VISIT(it->second);
318     }
319 
320     if (sbkSelf->ob_dict)
321         Py_VISIT(sbkSelf->ob_dict);
322     return 0;
323 }
324 
SbkObject_clear(PyObject * self)325 static int SbkObject_clear(PyObject *self)
326 {
327     auto *sbkSelf = reinterpret_cast<SbkObject *>(self);
328 
329     Shiboken::Object::removeParent(sbkSelf);
330 
331     if (sbkSelf->d->parentInfo)
332         _destroyParentInfo(sbkSelf, true);
333 
334     Shiboken::Object::clearReferences(sbkSelf);
335 
336     if (sbkSelf->ob_dict)
337         Py_CLEAR(sbkSelf->ob_dict);
338     return 0;
339 }
340 
341 static PyObject *SbkObject_GenericGetAttr(PyObject *obj, PyObject *name);
342 static int SbkObject_GenericSetAttr(PyObject *obj, PyObject *name, PyObject *value);
343 
344 static PyType_Slot SbkObject_Type_slots[] = {
345     {Py_tp_getattro, reinterpret_cast<void *>(SbkObject_GenericGetAttr)},
346     {Py_tp_setattro, reinterpret_cast<void *>(SbkObject_GenericSetAttr)},
347     {Py_tp_dealloc, reinterpret_cast<void *>(SbkDeallocWrapperWithPrivateDtor)},
348     {Py_tp_traverse, reinterpret_cast<void *>(SbkObject_traverse)},
349     {Py_tp_clear, reinterpret_cast<void *>(SbkObject_clear)},
350     // unsupported: {Py_tp_weaklistoffset, (void *)offsetof(SbkObject, weakreflist)},
351     {Py_tp_getset, reinterpret_cast<void *>(SbkObjectGetSetList)},
352     // unsupported: {Py_tp_dictoffset, (void *)offsetof(SbkObject, ob_dict)},
353     {0, nullptr}
354 };
355 static PyType_Spec SbkObject_Type_spec = {
356     "1:Shiboken.Object",
357     sizeof(SbkObject),
358     0,
359     Py_TPFLAGS_DEFAULT|Py_TPFLAGS_BASETYPE|Py_TPFLAGS_HAVE_GC,
360     SbkObject_Type_slots,
361 };
362 
363 
SbkObject_TypeF(void)364 SbkObjectType *SbkObject_TypeF(void)
365 {
366     static PyTypeObject *type = nullptr;
367     if (!type) {
368         type = reinterpret_cast<PyTypeObject *>(SbkType_FromSpec(&SbkObject_Type_spec));
369         Py_TYPE(type) = SbkObjectType_TypeF();
370         Py_INCREF(Py_TYPE(type));
371         type->tp_weaklistoffset = offsetof(SbkObject, weakreflist);
372         type->tp_dictoffset = offsetof(SbkObject, ob_dict);
373     }
374     return reinterpret_cast<SbkObjectType *>(type);
375 }
376 
mainThreadDeletionHandler(void *)377 static int mainThreadDeletionHandler(void *)
378 {
379     if (Py_IsInitialized())
380         Shiboken::BindingManager::instance().runDeletionInMainThread();
381     return 0;
382 }
383 
SbkDeallocWrapperCommon(PyObject * pyObj,bool canDelete)384 static void SbkDeallocWrapperCommon(PyObject *pyObj, bool canDelete)
385 {
386     auto *sbkObj = reinterpret_cast<SbkObject *>(pyObj);
387     PyTypeObject *pyType = Py_TYPE(pyObj);
388 
389     // Need to decref the type if this is the dealloc func; if type
390     // is subclassed, that dealloc func will decref (see subtype_dealloc
391     // in typeobject.c in the python sources)
392     bool needTypeDecref = (false
393                            || PyType_GetSlot(pyType, Py_tp_dealloc) == SbkDeallocWrapper
394                            || PyType_GetSlot(pyType, Py_tp_dealloc) == SbkDeallocWrapperWithPrivateDtor);
395     if (PepRuntime_38_flag) {
396         // PYSIDE-939: Additional rule: Also when a subtype is heap allocated,
397         // then the subtype_dealloc deref will be suppressed, and we need again
398         // to supply a decref.
399         needTypeDecref |= (pyType->tp_base->tp_flags & Py_TPFLAGS_HEAPTYPE) != 0;
400     }
401 
402 #if defined(__APPLE__)
403     // Just checking once that our assumptions are right.
404     if (false) {
405         void *p = PyType_GetSlot(pyType, Py_tp_dealloc);
406         Dl_info dl_info;
407         dladdr(p, &dl_info);
408         fprintf(stderr, "tp_dealloc is %s\n", dl_info.dli_sname);
409     }
410     // Gives one of our functions
411     //  "Sbk_object_dealloc"
412     //  "SbkDeallocWrapperWithPrivateDtor"
413     //  "SbkDeallocQAppWrapper"
414     //  "SbkDeallocWrapper"
415     // but for typedealloc_test.py we get
416     //  "subtype_dealloc"
417 #endif
418 
419     // Ensure that the GC is no longer tracking this object to avoid a
420     // possible reentrancy problem.  Since there are multiple steps involved
421     // in deallocating a SbkObject it is possible for the garbage collector to
422     // be invoked and it trying to delete this object while it is still in
423     // progress from the first time around, resulting in a double delete and a
424     // crash.
425     // PYSIDE-571: Some objects do not use GC, so check this!
426     if (PyObject_IS_GC(pyObj))
427         PyObject_GC_UnTrack(pyObj);
428 
429     // Check that Python is still initialized as sometimes this is called by a static destructor
430     // after Python interpeter is shutdown.
431     if (sbkObj->weakreflist && Py_IsInitialized())
432         PyObject_ClearWeakRefs(pyObj);
433 
434     // If I have ownership and is valid delete C++ pointer
435     SbkObjectTypePrivate *sotp{nullptr};
436     canDelete &= sbkObj->d->hasOwnership && sbkObj->d->validCppObject;
437     if (canDelete) {
438         sotp = PepType_SOTP(pyType);
439         if (sotp->delete_in_main_thread && Shiboken::currentThreadId() != Shiboken::mainThreadId()) {
440             auto &bindingManager = Shiboken::BindingManager::instance();
441             if (sotp->is_multicpp) {
442                  Shiboken::DtorAccumulatorVisitor visitor(sbkObj);
443                  Shiboken::walkThroughClassHierarchy(Py_TYPE(pyObj), &visitor);
444                  for (const auto &e : visitor.entries())
445                      bindingManager.addToDeletionInMainThread(e);
446             } else {
447                 Shiboken::DestructorEntry e{sotp->cpp_dtor, sbkObj->d->cptr[0]};
448                 bindingManager.addToDeletionInMainThread(e);
449             }
450             Py_AddPendingCall(mainThreadDeletionHandler, nullptr);
451             canDelete = false;
452         }
453     }
454 
455     PyObject *error_type, *error_value, *error_traceback;
456 
457     /* Save the current exception, if any. */
458     PyErr_Fetch(&error_type, &error_value, &error_traceback);
459 
460     if (canDelete) {
461         if (sotp->is_multicpp) {
462             Shiboken::DtorAccumulatorVisitor visitor(sbkObj);
463             Shiboken::walkThroughClassHierarchy(Py_TYPE(pyObj), &visitor);
464             Shiboken::Object::deallocData(sbkObj, true);
465             callDestructor(visitor.entries());
466         } else {
467             void *cptr = sbkObj->d->cptr[0];
468             Shiboken::Object::deallocData(sbkObj, true);
469 
470             Shiboken::ThreadStateSaver threadSaver;
471             if (Py_IsInitialized())
472                 threadSaver.save();
473             sotp->cpp_dtor(cptr);
474         }
475     } else {
476         Shiboken::Object::deallocData(sbkObj, true);
477     }
478 
479     /* Restore the saved exception. */
480     PyErr_Restore(error_type, error_value, error_traceback);
481 
482     if (needTypeDecref)
483         Py_DECREF(pyType);
484     if (PepRuntime_38_flag) {
485         // PYSIDE-939: Handling references correctly.
486         // This was not needed before Python 3.8 (Python issue 35810)
487         Py_DECREF(pyType);
488     }
489 }
490 
SbkDeallocWrapper(PyObject * pyObj)491 void SbkDeallocWrapper(PyObject *pyObj)
492 {
493     SbkDeallocWrapperCommon(pyObj, true);
494 }
495 
SbkDeallocQAppWrapper(PyObject * pyObj)496 void SbkDeallocQAppWrapper(PyObject *pyObj)
497 {
498     SbkDeallocWrapper(pyObj);
499     // PYSIDE-571: make sure to create a singleton deleted qApp.
500     Py_DECREF(MakeQAppWrapper(nullptr));
501 }
502 
SbkDeallocWrapperWithPrivateDtor(PyObject * self)503 void SbkDeallocWrapperWithPrivateDtor(PyObject *self)
504 {
505     SbkDeallocWrapperCommon(self, false);
506 }
507 
SbkObjectTypeDealloc(PyObject * pyObj)508 void SbkObjectTypeDealloc(PyObject *pyObj)
509 {
510     SbkObjectTypePrivate *sotp = PepType_SOTP(pyObj);
511     auto type = reinterpret_cast<PyTypeObject *>(pyObj);
512 
513     PyObject_GC_UnTrack(pyObj);
514 #ifndef Py_LIMITED_API
515     Py_TRASHCAN_SAFE_BEGIN(pyObj);
516 #endif
517     if (sotp) {
518         if (sotp->user_data && sotp->d_func) {
519             sotp->d_func(sotp->user_data);
520             sotp->user_data = nullptr;
521         }
522         free(sotp->original_name);
523         sotp->original_name = nullptr;
524         if (!Shiboken::ObjectType::isUserType(type))
525             Shiboken::Conversions::deleteConverter(sotp->converter);
526         delete sotp;
527         sotp = nullptr;
528     }
529 #ifndef Py_LIMITED_API
530     Py_TRASHCAN_SAFE_END(pyObj);
531 #endif
532     if (PepRuntime_38_flag) {
533         // PYSIDE-939: Handling references correctly.
534         // This was not needed before Python 3.8 (Python issue 35810)
535         Py_DECREF(Py_TYPE(pyObj));
536     }
537 }
538 
539 //////////////////////////////////////////////////////////////////////////////
540 //
541 // PYSIDE-1019: Support switchable extensions
542 //
543 // We simply exchange the complete class dicts.
544 //
545 //   This is done in                which replaces
546 //   ---------------                --------------
547 //   mangled_type_getattro          type_getattro
548 //   Sbk_TypeGet___dict__           type_dict
549 //   SbkObject_GenericGetAttr       PyObject_GenericGetAttr
550 //   SbkObject_GenericSetAttr       PyObject_GenericSetAttr
551 //
552 
initSelectableFeature(SelectableFeatureHook func)553 void initSelectableFeature(SelectableFeatureHook func)
554 {
555     SelectFeatureSet = func;
556 }
557 
mangled_type_getattro(PyTypeObject * type,PyObject * name)558 static PyObject *mangled_type_getattro(PyTypeObject *type, PyObject *name)
559 {
560     /*
561      * Note: This `type_getattro` version is only the default that comes
562      * from `PyType_Type.tp_getattro`. This does *not* interfere in any way
563      * with the complex `tp_getattro` of `QObject` and other instances.
564      * What we change here is the meta class of `QObject`.
565      */
566     if (SelectFeatureSet != nullptr)
567         type->tp_dict = SelectFeatureSet(type);
568     return type_getattro(reinterpret_cast<PyObject *>(type), name);
569 }
570 
Sbk_TypeGet___dict__(PyTypeObject * type,void * context)571 static PyObject *Sbk_TypeGet___dict__(PyTypeObject *type, void *context)
572 {
573     /*
574      * This is the override for getting a dict.
575      */
576     auto dict = type->tp_dict;
577     if (dict == NULL)
578         Py_RETURN_NONE;
579     if (SelectFeatureSet != nullptr)
580         dict = SelectFeatureSet(type);
581     return PyDictProxy_New(dict);
582 }
583 
584 // These functions replace the standard PyObject_Generic(Get|Set)Attr functions.
585 // They provide the default that "object" inherits.
586 // Everything else is directly handled by cppgenerator that calls `Feature::Select`.
SbkObject_GenericGetAttr(PyObject * obj,PyObject * name)587 static PyObject *SbkObject_GenericGetAttr(PyObject *obj, PyObject *name)
588 {
589     auto type = Py_TYPE(obj);
590     if (SelectFeatureSet != nullptr)
591         type->tp_dict = SelectFeatureSet(type);
592     return PyObject_GenericGetAttr(obj, name);
593 }
594 
SbkObject_GenericSetAttr(PyObject * obj,PyObject * name,PyObject * value)595 static int SbkObject_GenericSetAttr(PyObject *obj, PyObject *name, PyObject *value)
596 {
597     auto type = Py_TYPE(obj);
598     if (SelectFeatureSet != nullptr)
599         type->tp_dict = SelectFeatureSet(type);
600     return PyObject_GenericSetAttr(obj, name, value);
601 }
602 
603 // Caching the select Id.
SbkObjectType_GetReserved(PyTypeObject * type)604 int SbkObjectType_GetReserved(PyTypeObject *type)
605 {
606     auto ptr = PepType_SOTP(reinterpret_cast<SbkObjectType *>(type));
607     // PYSIDE-1019: During import PepType_SOTP is still zero.
608     if (ptr == nullptr)
609         return -1;
610     return ptr->pyside_reserved_bits;
611 }
612 
SbkObjectType_SetReserved(PyTypeObject * type,int value)613 void SbkObjectType_SetReserved(PyTypeObject *type, int value)
614 {
615     PepType_SOTP(reinterpret_cast<SbkObjectType *>(type))->pyside_reserved_bits = value;
616 }
617 
SbkObjectType_GetPropertyStrings(PyTypeObject * type)618 const char **SbkObjectType_GetPropertyStrings(PyTypeObject *type)
619 {
620     return PepType_SOTP(type)->propertyStrings;
621 }
622 
SbkObjectType_SetPropertyStrings(PyTypeObject * type,const char ** strings)623 void SbkObjectType_SetPropertyStrings(PyTypeObject *type, const char **strings)
624 {
625     PepType_SOTP(reinterpret_cast<SbkObjectType *>(type))->propertyStrings = strings;
626 }
627 
628 //
629 //////////////////////////////////////////////////////////////////////////////
630 
SbkObjectTypeTpNew(PyTypeObject * metatype,PyObject * args,PyObject * kwds)631 static PyObject *SbkObjectTypeTpNew(PyTypeObject *metatype, PyObject *args, PyObject *kwds)
632 {
633     // Check if all bases are new style before calling type.tp_new
634     // Was causing gc assert errors in test_bug704.py when
635     // this check happened after creating the type object.
636     // Argument parsing take from type.tp_new code.
637 
638     // PYSIDE-595: Also check if all bases allow inheritance.
639     // Before we changed to heap types, it was sufficient to remove the
640     // Py_TPFLAGS_BASETYPE flag. That does not work, because PySide does
641     // not respect this flag itself!
642     PyObject *name;
643     PyObject *pyBases;
644     PyObject *dict;
645     static const char *kwlist[] = { "name", "bases", "dict", nullptr};
646 
647     if (!PyArg_ParseTupleAndKeywords(args, kwds, "sO!O!:sbktype", const_cast<char **>(kwlist),
648                                      &name,
649                                      &PyTuple_Type, &pyBases,
650                                      &PyDict_Type, &dict))
651         return nullptr;
652 
653     for (int i=0, i_max=PyTuple_GET_SIZE(pyBases); i < i_max; i++) {
654         PyObject *baseType = PyTuple_GET_ITEM(pyBases, i);
655 #ifndef IS_PY3K
656         if (PyClass_Check(baseType)) {
657             PyErr_Format(PyExc_TypeError, "Invalid base class used in type %s. "
658                 "PySide only supports multiple inheritance from Python new style classes.",
659                 metatype->tp_name);
660             return 0;
661         }
662 #endif
663         if (reinterpret_cast<PyTypeObject *>(baseType)->tp_new == SbkDummyNew) {
664             // PYSIDE-595: A base class does not allow inheritance.
665             return SbkDummyNew(metatype, args, kwds);
666         }
667     }
668 
669     // The meta type creates a new type when the Python programmer extends a wrapped C++ class.
670     auto type_new = reinterpret_cast<newfunc>(PyType_Type.tp_new);
671 
672     // PYSIDE-939: This is a temporary patch that circumvents the problem
673     // with Py_TPFLAGS_METHOD_DESCRIPTOR until this is finally solved.
674     // PyType_Ready uses mro(). We need to temporarily remove the flag from it's type.
675     // We cannot use PyMethodDescr_Type since it is not exported by Python 2.7 .
676     static PyTypeObject *PyMethodDescr_TypePtr = Py_TYPE(
677         PyObject_GetAttr(reinterpret_cast<PyObject *>(&PyType_Type), Shiboken::PyName::mro()));
678     auto hold = PyMethodDescr_TypePtr->tp_flags;
679     PyMethodDescr_TypePtr->tp_flags &= ~Py_TPFLAGS_METHOD_DESCRIPTOR;
680     auto *newType = reinterpret_cast<SbkObjectType *>(type_new(metatype, args, kwds));
681     PyMethodDescr_TypePtr->tp_flags = hold;
682 
683     if (!newType)
684         return nullptr;
685 #if PY_VERSION_HEX < 0x03000000
686     // PYSIDE-1051: The newly created metatype needs the PYSIDE-816 wrapper, too.
687     if (patch_tp_new_wrapper(&newType->type) < 0)
688         return nullptr;
689 #endif
690 
691     Shiboken::ObjectType::initPrivateData(newType);
692     SbkObjectTypePrivate *sotp = PepType_SOTP(newType);
693 
694     const auto bases = Shiboken::getCppBaseClasses(reinterpret_cast<PyTypeObject *>(newType));
695     if (bases.size() == 1) {
696         SbkObjectTypePrivate *parentType = PepType_SOTP(bases.front());
697         sotp->mi_offsets = parentType->mi_offsets;
698         sotp->mi_init = parentType->mi_init;
699         sotp->mi_specialcast = parentType->mi_specialcast;
700         sotp->type_discovery = parentType->type_discovery;
701         sotp->cpp_dtor = parentType->cpp_dtor;
702         sotp->is_multicpp = 0;
703         sotp->converter = parentType->converter;
704     } else {
705         sotp->mi_offsets = nullptr;
706         sotp->mi_init = nullptr;
707         sotp->mi_specialcast = nullptr;
708         sotp->type_discovery = nullptr;
709         sotp->cpp_dtor = nullptr;
710         sotp->is_multicpp = 1;
711         sotp->converter = nullptr;
712     }
713     if (bases.size() == 1)
714         sotp->original_name = strdup(PepType_SOTP(bases.front())->original_name);
715     else
716         sotp->original_name = strdup("object");
717     sotp->user_data = nullptr;
718     sotp->d_func = nullptr;
719     sotp->is_user_type = 1;
720 
721     for (SbkObjectType *base : bases) {
722         if (PepType_SOTP(base)->subtype_init)
723             PepType_SOTP(base)->subtype_init(newType, args, kwds);
724     }
725     return reinterpret_cast<PyObject *>(newType);
726 }
727 
_setupNew(SbkObject * self,PyTypeObject * subtype)728 static PyObject *_setupNew(SbkObject *self, PyTypeObject *subtype)
729 {
730     Py_INCREF(reinterpret_cast<PyObject *>(subtype));
731     auto d = new SbkObjectPrivate;
732 
733     SbkObjectTypePrivate *sotp = PepType_SOTP(subtype);
734     int numBases = ((sotp && sotp->is_multicpp) ?
735         Shiboken::getNumberOfCppBaseClasses(subtype) : 1);
736     d->cptr = new void *[numBases];
737     std::memset(d->cptr, 0, sizeof(void *) *size_t(numBases));
738     d->hasOwnership = 1;
739     d->containsCppWrapper = 0;
740     d->validCppObject = 0;
741     d->parentInfo = nullptr;
742     d->referredObjects = nullptr;
743     d->cppObjectCreated = 0;
744     self->ob_dict = nullptr;
745     self->weakreflist = nullptr;
746     self->d = d;
747     return reinterpret_cast<PyObject *>(self);
748 }
749 
SbkObjectTpNew(PyTypeObject * subtype,PyObject *,PyObject *)750 PyObject *SbkObjectTpNew(PyTypeObject *subtype, PyObject *, PyObject *)
751 {
752     SbkObject *self = PyObject_GC_New(SbkObject, subtype);
753     PyObject *res = _setupNew(self, subtype);
754     PyObject_GC_Track(reinterpret_cast<PyObject *>(self));
755     return res;
756 }
757 
SbkQAppTpNew(PyTypeObject * subtype,PyObject *,PyObject *)758 PyObject *SbkQAppTpNew(PyTypeObject *subtype, PyObject *, PyObject *)
759 {
760     // PYSIDE-571:
761     // For qApp, we need to create a singleton Python object.
762     // We cannot track this with the GC, because it is a static variable!
763 
764     // Python 2 has a weird handling of flags in derived classes that Python 3
765     // does not have. Observed with bug_307.py.
766     // But it could theoretically also happen with Python3.
767     // Therefore we enforce that there is no GC flag, ever!
768 
769     // PYSIDE-560:
770     // We avoid to use this in Python 3, because we have a hard time to get
771     // write access to these flags
772 #ifndef IS_PY3K
773     if (PyType_HasFeature(subtype, Py_TPFLAGS_HAVE_GC)) {
774         subtype->tp_flags &= ~Py_TPFLAGS_HAVE_GC;
775         subtype->tp_free = PyObject_Del;
776     }
777 #endif
778     auto self = reinterpret_cast<SbkObject *>(MakeQAppWrapper(subtype));
779     return self == nullptr ? nullptr : _setupNew(self, subtype);
780 }
781 
SbkDummyNew(PyTypeObject * type,PyObject *,PyObject *)782 PyObject *SbkDummyNew(PyTypeObject *type, PyObject *, PyObject *)
783 {
784     // PYSIDE-595: Give the same error as type_call does when tp_new is NULL.
785     PyErr_Format(PyExc_TypeError,
786                  "cannot create '%.100s' instances ¯\\_(ツ)_/¯",
787                  type->tp_name);
788     return nullptr;
789 }
790 
SbkType_FromSpec(PyType_Spec * spec)791 PyObject *SbkType_FromSpec(PyType_Spec *spec)
792 {
793     return SbkType_FromSpecWithBases(spec, nullptr);
794 }
795 
SbkType_FromSpecWithBases(PyType_Spec * spec,PyObject * bases)796 PyObject *SbkType_FromSpecWithBases(PyType_Spec *spec, PyObject *bases)
797 {
798     // PYSIDE-1286: Generate correct __module__ and __qualname__
799     // The name field can now be extended by an "n:" prefix which is
800     // the number of modules in the name. The default is 1.
801     //
802     // Example:
803     //    "2:mainmod.submod.mainclass.subclass"
804     // results in
805     //    __module__   : "mainmod.submod"
806     //    __qualname__ : "mainclass.subclass"
807     //    __name__     : "subclass"
808 
809     PyType_Spec new_spec = *spec;
810     const char *colon = strchr(spec->name, ':');
811     assert(colon);
812     int package_level = atoi(spec->name);
813     const char *mod = new_spec.name = colon + 1;
814 
815     PyObject *type = PyType_FromSpecWithBases(&new_spec, bases);
816     if (type == nullptr)
817         return nullptr;
818 
819     const char *qual = mod;
820     for (int idx = package_level; idx > 0; --idx) {
821         const char *dot = strchr(qual, '.');
822         if (!dot)
823             break;
824         qual = dot + 1;
825     }
826     int mlen = qual - mod - 1;
827     Shiboken::AutoDecRef module(Shiboken::String::fromCString(mod, mlen));
828     Shiboken::AutoDecRef qualname(Shiboken::String::fromCString(qual));
829     if (PyObject_SetAttr(type, Shiboken::PyMagicName::module(), module) < 0)
830         return nullptr;
831     if (PyObject_SetAttr(type, Shiboken::PyMagicName::qualname(), qualname) < 0)
832         return nullptr;
833     return type;
834 }
835 
836 // PYSIDE-74: Fallback used in all types now.
FallbackRichCompare(PyObject * self,PyObject * other,int op)837 PyObject *FallbackRichCompare(PyObject *self, PyObject *other, int op)
838 {
839     // This is a very simple implementation that supplies a simple identity.
840     static const char * const opstrings[] = {"<", "<=", "==", "!=", ">", ">="};
841     PyObject *res;
842 
843     switch (op) {
844 
845     case Py_EQ:
846         res = (self == other) ? Py_True : Py_False;
847         break;
848     case Py_NE:
849         res = (self != other) ? Py_True : Py_False;
850         break;
851     default:
852         PyErr_Format(PyExc_TypeError,
853                      "'%s' not supported between instances of '%.100s' and '%.100s'",
854                      opstrings[op],
855                      self->ob_type->tp_name,
856                      other->ob_type->tp_name);
857         return NULL;
858     }
859     Py_INCREF(res);
860     return res;
861 }
862 
863 } //extern "C"
864 
865 
866 namespace
867 {
868 
_destroyParentInfo(SbkObject * obj,bool keepReference)869 void _destroyParentInfo(SbkObject *obj, bool keepReference)
870 {
871     Shiboken::ParentInfo *pInfo = obj->d->parentInfo;
872     if (pInfo) {
873         while(!pInfo->children.empty()) {
874             SbkObject *first = *pInfo->children.begin();
875             // Mark child as invalid
876             Shiboken::Object::invalidate(first);
877             Shiboken::Object::removeParent(first, false, keepReference);
878         }
879         Shiboken::Object::removeParent(obj, false);
880     }
881 }
882 
883 }
884 
885 namespace Shiboken
886 {
walkThroughClassHierarchy(PyTypeObject * currentType,HierarchyVisitor * visitor)887 bool walkThroughClassHierarchy(PyTypeObject *currentType, HierarchyVisitor *visitor)
888 {
889     PyObject *bases = currentType->tp_bases;
890     Py_ssize_t numBases = PyTuple_GET_SIZE(bases);
891     bool result = false;
892     for (int i = 0; !result && i < numBases; ++i) {
893         auto type = reinterpret_cast<PyTypeObject *>(PyTuple_GET_ITEM(bases, i));
894         if (PyType_IsSubtype(type, reinterpret_cast<PyTypeObject *>(SbkObject_TypeF()))) {
895             auto sbkType = reinterpret_cast<SbkObjectType *>(type);
896             result = PepType_SOTP(sbkType)->is_user_type
897                      ? walkThroughClassHierarchy(type, visitor) : visitor->visit(sbkType);
898         }
899     }
900     return result;
901 }
902 
903 // Wrapper metatype and base type ----------------------------------------------------------
904 
905 HierarchyVisitor::HierarchyVisitor() = default;
906 HierarchyVisitor::~HierarchyVisitor() = default;
907 
visit(SbkObjectType *)908 bool BaseCountVisitor::visit(SbkObjectType *)
909 {
910     m_count++;
911     return false;
912 }
913 
visit(SbkObjectType * node)914 bool BaseAccumulatorVisitor::visit(SbkObjectType *node)
915 {
916     m_bases.push_back(node);
917     return false;
918 }
919 
visit(SbkObjectType * node)920 bool GetIndexVisitor::visit(SbkObjectType *node)
921 {
922     m_index++;
923     return PyType_IsSubtype(reinterpret_cast<PyTypeObject *>(node), m_desiredType);
924 }
925 
visit(SbkObjectType * node)926 bool DtorAccumulatorVisitor::visit(SbkObjectType *node)
927 {
928     m_entries.push_back(DestructorEntry{PepType_SOTP(node)->cpp_dtor,
929                                         m_pyObject->d->cptr[m_entries.size()]});
930     return false;
931 }
932 
933 void _initMainThreadId(); // helper.cpp
934 
935 namespace Conversions { void init(); }
936 
init()937 void init()
938 {
939     static bool shibokenAlreadInitialised = false;
940     if (shibokenAlreadInitialised)
941         return;
942 
943     _initMainThreadId();
944 
945     Conversions::init();
946 
947 #if PY_VERSION_HEX < 0x03070000
948     PyEval_InitThreads();
949 #endif
950 
951     //Init private data
952     Pep384_Init();
953 
954     Shiboken::ObjectType::initPrivateData(SbkObject_TypeF());
955 
956     if (PyType_Ready(SbkEnumType_TypeF()) < 0)
957         Py_FatalError("[libshiboken] Failed to initialize Shiboken.SbkEnumType metatype.");
958 
959     if (PyType_Ready(SbkObjectType_TypeF()) < 0)
960         Py_FatalError("[libshiboken] Failed to initialize Shiboken.BaseWrapperType metatype.");
961 
962     if (PyType_Ready(reinterpret_cast<PyTypeObject *>(SbkObject_TypeF())) < 0)
963         Py_FatalError("[libshiboken] Failed to initialize Shiboken.BaseWrapper type.");
964 
965     VoidPtr::init();
966 
967     shibokenAlreadInitialised = true;
968 }
969 
970 // setErrorAboutWrongArguments now gets overload info from the signature module.
setErrorAboutWrongArguments(PyObject * args,const char * funcName)971 void setErrorAboutWrongArguments(PyObject *args, const char *funcName)
972 {
973     SetError_Argument(args, funcName);
974 }
975 
976 class FindBaseTypeVisitor : public HierarchyVisitor
977 {
978 public:
FindBaseTypeVisitor(PyTypeObject * typeToFind)979     explicit FindBaseTypeVisitor(PyTypeObject *typeToFind) : m_typeToFind(typeToFind) {}
980 
visit(SbkObjectType * node)981     bool visit(SbkObjectType *node) override
982     {
983         return reinterpret_cast<PyTypeObject *>(node) == m_typeToFind;
984     }
985 
986 private:
987     PyTypeObject *m_typeToFind;
988 };
989 
splitPyObject(PyObject * pyObj)990 std::vector<SbkObject *> splitPyObject(PyObject *pyObj)
991 {
992     std::vector<SbkObject *> result;
993     if (PySequence_Check(pyObj)) {
994         AutoDecRef lst(PySequence_Fast(pyObj, "Invalid keep reference object."));
995         if (!lst.isNull()) {
996             for (Py_ssize_t i = 0, i_max = PySequence_Fast_GET_SIZE(lst.object()); i < i_max; ++i) {
997                 PyObject *item = PySequence_Fast_GET_ITEM(lst.object(), i);
998                 if (Object::checkType(item))
999                     result.push_back(reinterpret_cast<SbkObject *>(item));
1000             }
1001         }
1002     } else {
1003         result.push_back(reinterpret_cast<SbkObject *>(pyObj));
1004     }
1005     return result;
1006 }
1007 
1008 template <class Iterator>
decRefPyObjectList(Iterator i1,Iterator i2)1009 inline void decRefPyObjectList(Iterator i1, Iterator i2)
1010 {
1011     for (; i1 != i2; ++i1)
1012         Py_DECREF(i1->second);
1013 }
1014 
1015 namespace ObjectType
1016 {
1017 
checkType(PyTypeObject * type)1018 bool checkType(PyTypeObject *type)
1019 {
1020     return PyType_IsSubtype(type, reinterpret_cast<PyTypeObject *>(SbkObject_TypeF())) != 0;
1021 }
1022 
isUserType(PyTypeObject * type)1023 bool isUserType(PyTypeObject *type)
1024 {
1025     return checkType(type) && PepType_SOTP(type)->is_user_type;
1026 }
1027 
canCallConstructor(PyTypeObject * myType,PyTypeObject * ctorType)1028 bool canCallConstructor(PyTypeObject *myType, PyTypeObject *ctorType)
1029 {
1030     FindBaseTypeVisitor visitor(ctorType);
1031     if (!walkThroughClassHierarchy(myType, &visitor)) {
1032         PyErr_Format(PyExc_TypeError, "%s isn't a direct base class of %s", ctorType->tp_name, myType->tp_name);
1033         return false;
1034     }
1035     return true;
1036 }
1037 
hasCast(SbkObjectType * type)1038 bool hasCast(SbkObjectType *type)
1039 {
1040     return PepType_SOTP(type)->mi_specialcast != nullptr;
1041 }
1042 
cast(SbkObjectType * sourceType,SbkObject * obj,PyTypeObject * targetType)1043 void *cast(SbkObjectType *sourceType, SbkObject *obj, PyTypeObject *targetType)
1044 {
1045     return PepType_SOTP(sourceType)->mi_specialcast(Object::cppPointer(obj, targetType),
1046         reinterpret_cast<SbkObjectType *>(targetType));
1047 }
1048 
setCastFunction(SbkObjectType * type,SpecialCastFunction func)1049 void setCastFunction(SbkObjectType *type, SpecialCastFunction func)
1050 {
1051     PepType_SOTP(type)->mi_specialcast = func;
1052 }
1053 
setOriginalName(SbkObjectType * type,const char * name)1054 void setOriginalName(SbkObjectType *type, const char *name)
1055 {
1056     SbkObjectTypePrivate *sotp = PepType_SOTP(type);
1057     if (sotp->original_name)
1058         free(sotp->original_name);
1059     sotp->original_name = strdup(name);
1060 }
1061 
getOriginalName(SbkObjectType * type)1062 const char *getOriginalName(SbkObjectType *type)
1063 {
1064     return PepType_SOTP(type)->original_name;
1065 }
1066 
setTypeDiscoveryFunctionV2(SbkObjectType * type,TypeDiscoveryFuncV2 func)1067 void setTypeDiscoveryFunctionV2(SbkObjectType *type, TypeDiscoveryFuncV2 func)
1068 {
1069     PepType_SOTP(type)->type_discovery = func;
1070 }
1071 
copyMultipleInheritance(SbkObjectType * type,SbkObjectType * other)1072 void copyMultipleInheritance(SbkObjectType *type, SbkObjectType *other)
1073 {
1074     PepType_SOTP(type)->mi_init = PepType_SOTP(other)->mi_init;
1075     PepType_SOTP(type)->mi_offsets = PepType_SOTP(other)->mi_offsets;
1076     PepType_SOTP(type)->mi_specialcast = PepType_SOTP(other)->mi_specialcast;
1077 }
1078 
setMultipleInheritanceFunction(SbkObjectType * type,MultipleInheritanceInitFunction function)1079 void setMultipleInheritanceFunction(SbkObjectType *type, MultipleInheritanceInitFunction function)
1080 {
1081     PepType_SOTP(type)->mi_init = function;
1082 }
1083 
getMultipleInheritanceFunction(SbkObjectType * type)1084 MultipleInheritanceInitFunction getMultipleInheritanceFunction(SbkObjectType *type)
1085 {
1086     return PepType_SOTP(type)->mi_init;
1087 }
1088 
setDestructorFunction(SbkObjectType * type,ObjectDestructor func)1089 void setDestructorFunction(SbkObjectType *type, ObjectDestructor func)
1090 {
1091     PepType_SOTP(type)->cpp_dtor = func;
1092 }
1093 
initPrivateData(SbkObjectType * type)1094 void initPrivateData(SbkObjectType *type)
1095 {
1096     PepType_SOTP(type) = new SbkObjectTypePrivate;
1097     memset(PepType_SOTP(type), 0, sizeof(SbkObjectTypePrivate));
1098 }
1099 
1100 SbkObjectType *
introduceWrapperType(PyObject * enclosingObject,const char * typeName,const char * originalName,PyType_Spec * typeSpec,ObjectDestructor cppObjDtor,SbkObjectType * baseType,PyObject * baseTypes,unsigned wrapperFlags)1101 introduceWrapperType(PyObject *enclosingObject,
1102                      const char *typeName,
1103                      const char *originalName,
1104                      PyType_Spec *typeSpec,
1105                      ObjectDestructor cppObjDtor,
1106                      SbkObjectType *baseType,
1107                      PyObject *baseTypes,
1108                      unsigned wrapperFlags)
1109 {
1110     typeSpec->slots[0].pfunc = reinterpret_cast<void *>(baseType ? baseType : SbkObject_TypeF());
1111 
1112     PyObject *heaptype = SbkType_FromSpecWithBases(typeSpec, baseTypes);
1113     Py_TYPE(heaptype) = SbkObjectType_TypeF();
1114     Py_INCREF(Py_TYPE(heaptype));
1115     auto *type = reinterpret_cast<SbkObjectType *>(heaptype);
1116 #if PY_VERSION_HEX < 0x03000000
1117     // PYSIDE-1051: The newly created type needs the PYSIDE-816 wrapper, too.
1118     if (patch_tp_new_wrapper(&type->type) < 0)
1119         return nullptr;
1120 #endif
1121     if (baseType) {
1122         if (baseTypes) {
1123             for (int i = 0; i < PySequence_Fast_GET_SIZE(baseTypes); ++i)
1124                 BindingManager::instance().addClassInheritance(reinterpret_cast<SbkObjectType *>(PySequence_Fast_GET_ITEM(baseTypes, i)), type);
1125         } else {
1126             BindingManager::instance().addClassInheritance(baseType, type);
1127         }
1128     }
1129     if (PyType_Ready(reinterpret_cast<PyTypeObject *>(type)) < 0)
1130         return nullptr;
1131 
1132     initPrivateData(type);
1133     auto sotp = PepType_SOTP(type);
1134     if (wrapperFlags & DeleteInMainThread)
1135         sotp->delete_in_main_thread = 1;
1136 
1137     setOriginalName(type, originalName);
1138     setDestructorFunction(type, cppObjDtor);
1139     auto *ob_type = reinterpret_cast<PyObject *>(type);
1140 
1141     if (wrapperFlags & InnerClass)
1142         return PyDict_SetItemString(enclosingObject, typeName, ob_type) == 0 ? type : nullptr;
1143 
1144     // PyModule_AddObject steals type's reference.
1145     Py_INCREF(ob_type);
1146     if (PyModule_AddObject(enclosingObject, typeName, ob_type) != 0) {
1147         std::cerr << "Warning: " << __FUNCTION__ << " returns nullptr for "
1148             << typeName << '/' << originalName << " due to PyModule_AddObject(enclosingObject="
1149             << enclosingObject << ",ob_type=" << ob_type << ") failing\n";
1150         return nullptr;
1151     }
1152     return type;
1153 }
1154 
setSubTypeInitHook(SbkObjectType * type,SubTypeInitHook func)1155 void setSubTypeInitHook(SbkObjectType *type, SubTypeInitHook func)
1156 {
1157     PepType_SOTP(type)->subtype_init = func;
1158 }
1159 
getTypeUserData(SbkObjectType * type)1160 void *getTypeUserData(SbkObjectType *type)
1161 {
1162     return PepType_SOTP(type)->user_data;
1163 }
1164 
setTypeUserData(SbkObjectType * type,void * userData,DeleteUserDataFunc d_func)1165 void setTypeUserData(SbkObjectType *type, void *userData, DeleteUserDataFunc d_func)
1166 {
1167     SbkObjectTypePrivate *sotp = PepType_SOTP(type);
1168     sotp->user_data = userData;
1169     sotp->d_func = d_func;
1170 }
1171 
1172 // Try to find the exact type of cptr.
typeForTypeName(const char * typeName)1173 SbkObjectType *typeForTypeName(const char *typeName)
1174 {
1175     SbkObjectType *result{};
1176     if (typeName) {
1177         if (PyTypeObject *pyType = Shiboken::Conversions::getPythonTypeObject(typeName))
1178             result = reinterpret_cast<SbkObjectType *>(pyType);
1179     }
1180     return result;
1181 }
1182 
hasSpecialCastFunction(SbkObjectType * sbkType)1183 bool hasSpecialCastFunction(SbkObjectType *sbkType)
1184 {
1185     const SbkObjectTypePrivate *d = PepType_SOTP(sbkType);
1186     return d != nullptr && d->mi_specialcast != nullptr;
1187 }
1188 
1189 } // namespace ObjectType
1190 
1191 
1192 namespace Object
1193 {
1194 
1195 static void recursive_invalidate(SbkObject *self, std::set<SbkObject *>& seen);
1196 
checkType(PyObject * pyObj)1197 bool checkType(PyObject *pyObj)
1198 {
1199     return ObjectType::checkType(Py_TYPE(pyObj));
1200 }
1201 
isUserType(PyObject * pyObj)1202 bool isUserType(PyObject *pyObj)
1203 {
1204     return ObjectType::isUserType(Py_TYPE(pyObj));
1205 }
1206 
hash(PyObject * pyObj)1207 Py_hash_t hash(PyObject *pyObj)
1208 {
1209     assert(Shiboken::Object::checkType(pyObj));
1210     return reinterpret_cast<Py_hash_t>(pyObj);
1211 }
1212 
setSequenceOwnership(PyObject * pyObj,bool owner)1213 static void setSequenceOwnership(PyObject *pyObj, bool owner)
1214 {
1215 
1216     bool has_length = true;
1217 
1218     if (!pyObj)
1219         return;
1220 
1221     if (PySequence_Size(pyObj) < 0) {
1222         PyErr_Clear();
1223         has_length = false;
1224     }
1225 
1226     if (PySequence_Check(pyObj) && has_length) {
1227         Py_ssize_t size = PySequence_Size(pyObj);
1228         if (size > 0) {
1229             const auto objs = splitPyObject(pyObj);
1230             if (owner) {
1231                 for (SbkObject *o : objs)
1232                     getOwnership(o);
1233             } else {
1234                 for (SbkObject *o : objs)
1235                     releaseOwnership(o);
1236             }
1237         }
1238     } else if (Object::checkType(pyObj)) {
1239         if (owner)
1240             getOwnership(reinterpret_cast<SbkObject *>(pyObj));
1241         else
1242             releaseOwnership(reinterpret_cast<SbkObject *>(pyObj));
1243     }
1244 }
1245 
setValidCpp(SbkObject * pyObj,bool value)1246 void setValidCpp(SbkObject *pyObj, bool value)
1247 {
1248     pyObj->d->validCppObject = value;
1249 }
1250 
setHasCppWrapper(SbkObject * pyObj,bool value)1251 void setHasCppWrapper(SbkObject *pyObj, bool value)
1252 {
1253     pyObj->d->containsCppWrapper = value;
1254 }
1255 
hasCppWrapper(SbkObject * pyObj)1256 bool hasCppWrapper(SbkObject *pyObj)
1257 {
1258     return pyObj->d->containsCppWrapper;
1259 }
1260 
wasCreatedByPython(SbkObject * pyObj)1261 bool wasCreatedByPython(SbkObject *pyObj)
1262 {
1263     return pyObj->d->cppObjectCreated;
1264 }
1265 
callCppDestructors(SbkObject * pyObj)1266 void callCppDestructors(SbkObject *pyObj)
1267 {
1268     PyTypeObject *type = Py_TYPE(pyObj);
1269     SbkObjectTypePrivate *sotp = PepType_SOTP(type);
1270     if (sotp->is_multicpp) {
1271         Shiboken::DtorAccumulatorVisitor visitor(pyObj);
1272         Shiboken::walkThroughClassHierarchy(type, &visitor);
1273         callDestructor(visitor.entries());
1274     } else {
1275         Shiboken::ThreadStateSaver threadSaver;
1276         threadSaver.save();
1277         sotp->cpp_dtor(pyObj->d->cptr[0]);
1278     }
1279 
1280     /* invalidate needs to be called before deleting pointer array because
1281        it needs to delete entries for them from the BindingManager hash table;
1282        also release wrapper explicitly if object contains C++ wrapper because
1283        invalidate doesn't */
1284     invalidate(pyObj);
1285     if (pyObj->d->validCppObject && pyObj->d->containsCppWrapper) {
1286       BindingManager::instance().releaseWrapper(pyObj);
1287     }
1288 
1289     delete[] pyObj->d->cptr;
1290     pyObj->d->cptr = nullptr;
1291     pyObj->d->validCppObject = false;
1292 }
1293 
hasOwnership(SbkObject * pyObj)1294 bool hasOwnership(SbkObject *pyObj)
1295 {
1296     return pyObj->d->hasOwnership;
1297 }
1298 
getOwnership(SbkObject * self)1299 void getOwnership(SbkObject *self)
1300 {
1301     // skip if already have the ownership
1302     if (self->d->hasOwnership)
1303         return;
1304 
1305     // skip if this object has parent
1306     if (self->d->parentInfo && self->d->parentInfo->parent)
1307         return;
1308 
1309     // Get back the ownership
1310     self->d->hasOwnership = true;
1311 
1312     if (self->d->containsCppWrapper)
1313         Py_DECREF(reinterpret_cast<PyObject *>(self)); // Remove extra ref
1314     else
1315         makeValid(self); // Make the object valid again
1316 }
1317 
getOwnership(PyObject * pyObj)1318 void getOwnership(PyObject *pyObj)
1319 {
1320     if (pyObj)
1321         setSequenceOwnership(pyObj, true);
1322 }
1323 
releaseOwnership(SbkObject * self)1324 void releaseOwnership(SbkObject *self)
1325 {
1326     // skip if the ownership have already moved to c++
1327     auto *selfType = reinterpret_cast<SbkObjectType *>(Py_TYPE(self));
1328     if (!self->d->hasOwnership || Shiboken::Conversions::pythonTypeIsValueType(PepType_SOTP(selfType)->converter))
1329         return;
1330 
1331     // remove object ownership
1332     self->d->hasOwnership = false;
1333 
1334     // If We have control over object life
1335     if (self->d->containsCppWrapper)
1336         Py_INCREF(reinterpret_cast<PyObject *>(self)); // keep the python object alive until the wrapper destructor call
1337     else
1338         invalidate(self); // If I do not know when this object will die We need to invalidate this to avoid use after
1339 }
1340 
releaseOwnership(PyObject * self)1341 void releaseOwnership(PyObject *self)
1342 {
1343     setSequenceOwnership(self, false);
1344 }
1345 
1346 /* Needed forward declarations */
1347 static void recursive_invalidate(PyObject *pyobj, std::set<SbkObject *>& seen);
1348 static void recursive_invalidate(SbkObject *self, std::set<SbkObject *> &seen);
1349 
invalidate(PyObject * pyobj)1350 void invalidate(PyObject *pyobj)
1351 {
1352     std::set<SbkObject *> seen;
1353     recursive_invalidate(pyobj, seen);
1354 }
1355 
invalidate(SbkObject * self)1356 void invalidate(SbkObject *self)
1357 {
1358     std::set<SbkObject *> seen;
1359     recursive_invalidate(self, seen);
1360 }
1361 
recursive_invalidate(PyObject * pyobj,std::set<SbkObject * > & seen)1362 static void recursive_invalidate(PyObject *pyobj, std::set<SbkObject *> &seen)
1363 {
1364     const auto objs = splitPyObject(pyobj);
1365     for (SbkObject *o : objs)
1366         recursive_invalidate(o, seen);
1367 }
1368 
recursive_invalidate(SbkObject * self,std::set<SbkObject * > & seen)1369 static void recursive_invalidate(SbkObject *self, std::set<SbkObject *> &seen)
1370 {
1371     // Skip if this object not is a valid object or if it's already been seen
1372     if (!self || reinterpret_cast<PyObject *>(self) == Py_None || seen.find(self) != seen.end())
1373         return;
1374     seen.insert(self);
1375 
1376     if (!self->d->containsCppWrapper) {
1377         self->d->validCppObject = false; // Mark object as invalid only if this is not a wrapper class
1378         BindingManager::instance().releaseWrapper(self);
1379     }
1380 
1381     // If it is a parent invalidate all children.
1382     if (self->d->parentInfo) {
1383         // Create a copy because this list can be changed during the process
1384         ChildrenList copy = self->d->parentInfo->children;
1385 
1386         for (SbkObject *child : copy) {
1387             // invalidate the child
1388             recursive_invalidate(child, seen);
1389 
1390             // if the parent not is a wrapper class, then remove children from him, because We do not know when this object will be destroyed
1391             if (!self->d->validCppObject)
1392                 removeParent(child, true, true);
1393         }
1394     }
1395 
1396     // If has ref to other objects invalidate all
1397     if (self->d->referredObjects) {
1398         RefCountMap &refCountMap = *(self->d->referredObjects);
1399         for (auto it = refCountMap.begin(), end = refCountMap.end(); it != end; ++it)
1400             recursive_invalidate(it->second, seen);
1401     }
1402 }
1403 
makeValid(SbkObject * self)1404 void makeValid(SbkObject *self)
1405 {
1406     // Skip if this object not is a valid object
1407     if (!self || reinterpret_cast<PyObject *>(self) == Py_None || self->d->validCppObject)
1408         return;
1409 
1410     // Mark object as invalid only if this is not a wrapper class
1411     self->d->validCppObject = true;
1412 
1413     // If it is a parent make  all children valid
1414     if (self->d->parentInfo) {
1415         for (SbkObject *child : self->d->parentInfo->children)
1416             makeValid(child);
1417     }
1418 
1419     // If has ref to other objects make all valid again
1420     if (self->d->referredObjects) {
1421         RefCountMap &refCountMap = *(self->d->referredObjects);
1422         RefCountMap::iterator iter;
1423         for (auto it = refCountMap.begin(), end = refCountMap.end(); it != end; ++it) {
1424             if (Shiboken::Object::checkType(it->second))
1425                 makeValid(reinterpret_cast<SbkObject *>(it->second));
1426         }
1427     }
1428 }
1429 
cppPointer(SbkObject * pyObj,PyTypeObject * desiredType)1430 void *cppPointer(SbkObject *pyObj, PyTypeObject *desiredType)
1431 {
1432     PyTypeObject *type = Py_TYPE(pyObj);
1433     int idx = 0;
1434     if (PepType_SOTP(reinterpret_cast<SbkObjectType *>(type))->is_multicpp)
1435         idx = getTypeIndexOnHierarchy(type, desiredType);
1436     if (pyObj->d->cptr)
1437         return pyObj->d->cptr[idx];
1438     return nullptr;
1439 }
1440 
cppPointers(SbkObject * pyObj)1441 std::vector<void *> cppPointers(SbkObject *pyObj)
1442 {
1443     int n = getNumberOfCppBaseClasses(Py_TYPE(pyObj));
1444     std::vector<void *> ptrs(n);
1445     for (int i = 0; i < n; ++i)
1446         ptrs[i] = pyObj->d->cptr[i];
1447     return ptrs;
1448 }
1449 
1450 
setCppPointer(SbkObject * sbkObj,PyTypeObject * desiredType,void * cptr)1451 bool setCppPointer(SbkObject *sbkObj, PyTypeObject *desiredType, void *cptr)
1452 {
1453     int idx = 0;
1454     PyTypeObject *type = Py_TYPE(sbkObj);
1455     if (PepType_SOTP(type)->is_multicpp)
1456         idx = getTypeIndexOnHierarchy(type, desiredType);
1457 
1458     const bool alreadyInitialized = sbkObj->d->cptr[idx] != nullptr;
1459     if (alreadyInitialized)
1460         PyErr_SetString(PyExc_RuntimeError, "You can't initialize an object twice!");
1461     else
1462         sbkObj->d->cptr[idx] = cptr;
1463 
1464     sbkObj->d->cppObjectCreated = true;
1465     return !alreadyInitialized;
1466 }
1467 
isValid(PyObject * pyObj)1468 bool isValid(PyObject *pyObj)
1469 {
1470     if (!pyObj || pyObj == Py_None
1471         || Py_TYPE(Py_TYPE(pyObj)) != SbkObjectType_TypeF()) {
1472         return true;
1473     }
1474 
1475     auto priv = reinterpret_cast<SbkObject *>(pyObj)->d;
1476 
1477     if (!priv->cppObjectCreated && isUserType(pyObj)) {
1478         PyErr_Format(PyExc_RuntimeError, "'__init__' method of object's base class (%s) not called.",
1479                      Py_TYPE(pyObj)->tp_name);
1480         return false;
1481     }
1482 
1483     if (!priv->validCppObject) {
1484         PyErr_Format(PyExc_RuntimeError, "Internal C++ object (%s) already deleted.",
1485                      Py_TYPE(pyObj)->tp_name);
1486         return false;
1487     }
1488 
1489     return true;
1490 }
1491 
isValid(SbkObject * pyObj,bool throwPyError)1492 bool isValid(SbkObject *pyObj, bool throwPyError)
1493 {
1494     if (!pyObj)
1495         return false;
1496 
1497     SbkObjectPrivate *priv = pyObj->d;
1498     if (!priv->cppObjectCreated && isUserType(reinterpret_cast<PyObject *>(pyObj))) {
1499         if (throwPyError)
1500             PyErr_Format(PyExc_RuntimeError, "Base constructor of the object (%s) not called.",
1501                          Py_TYPE(pyObj)->tp_name);
1502         return false;
1503     }
1504 
1505     if (!priv->validCppObject) {
1506         if (throwPyError)
1507             PyErr_Format(PyExc_RuntimeError, "Internal C++ object (%s) already deleted.",
1508                          (Py_TYPE(pyObj))->tp_name);
1509         return false;
1510     }
1511 
1512     return true;
1513 }
1514 
isValid(PyObject * pyObj,bool throwPyError)1515 bool isValid(PyObject *pyObj, bool throwPyError)
1516 {
1517     if (!pyObj || pyObj == Py_None ||
1518         !PyType_IsSubtype(Py_TYPE(pyObj), reinterpret_cast<PyTypeObject *>(SbkObject_TypeF()))) {
1519         return true;
1520     }
1521     return isValid(reinterpret_cast<SbkObject *>(pyObj), throwPyError);
1522 }
1523 
findColocatedChild(SbkObject * wrapper,const SbkObjectType * instanceType)1524 SbkObject *findColocatedChild(SbkObject *wrapper,
1525                               const SbkObjectType *instanceType)
1526 {
1527     // Degenerate case, wrapper is the correct wrapper.
1528     if (reinterpret_cast<const void *>(Py_TYPE(wrapper)) == reinterpret_cast<const void *>(instanceType))
1529         return wrapper;
1530 
1531     if (!(wrapper->d && wrapper->d->cptr))
1532         return nullptr;
1533 
1534     ParentInfo *pInfo = wrapper->d->parentInfo;
1535     if (!pInfo)
1536         return nullptr;
1537 
1538     ChildrenList &children = pInfo->children;
1539 
1540     for (SbkObject *child : children) {
1541         if (!(child->d && child->d->cptr))
1542             continue;
1543         if (child->d->cptr[0] == wrapper->d->cptr[0]) {
1544             return reinterpret_cast<const void *>(Py_TYPE(child)) == reinterpret_cast<const void *>(instanceType)
1545                 ? child : findColocatedChild(child, instanceType);
1546         }
1547     }
1548     return nullptr;
1549 }
1550 
newObject(SbkObjectType * instanceType,void * cptr,bool hasOwnership,bool isExactType,const char * typeName)1551 PyObject *newObject(SbkObjectType *instanceType,
1552                     void *cptr,
1553                     bool hasOwnership,
1554                     bool isExactType,
1555                     const char *typeName)
1556 {
1557     // Try to find the exact type of cptr.
1558     if (!isExactType) {
1559         if (SbkObjectType *exactType = ObjectType::typeForTypeName(typeName))
1560             instanceType = exactType;
1561         else
1562             instanceType = BindingManager::instance().resolveType(&cptr, instanceType);
1563     }
1564 
1565     bool shouldCreate = true;
1566     bool shouldRegister = true;
1567     SbkObject *self = nullptr;
1568 
1569     // Some logic to ensure that colocated child field does not overwrite the parent
1570     if (BindingManager::instance().hasWrapper(cptr)) {
1571         SbkObject *existingWrapper = BindingManager::instance().retrieveWrapper(cptr);
1572 
1573         self = findColocatedChild(existingWrapper, instanceType);
1574         if (self) {
1575             // Wrapper already registered for cptr.
1576             // This should not ideally happen, binding code should know when a wrapper
1577             // already exists and retrieve it instead.
1578             shouldRegister = shouldCreate = false;
1579         } else if (hasOwnership &&
1580                   (!(Shiboken::Object::hasCppWrapper(existingWrapper) ||
1581                      Shiboken::Object::hasOwnership(existingWrapper)))) {
1582             // Old wrapper is likely junk, since we have ownership and it doesn't.
1583             BindingManager::instance().releaseWrapper(existingWrapper);
1584         } else {
1585             // Old wrapper may be junk caused by some bug in identifying object deletion
1586             // but it may not be junk when a colocated field is accessed for an
1587             // object which was not created by python (returned from c++ factory function).
1588             // Hence we cannot release the wrapper confidently so we do not register.
1589             shouldRegister = false;
1590         }
1591     }
1592 
1593     if (shouldCreate) {
1594         self = reinterpret_cast<SbkObject *>(SbkObjectTpNew(reinterpret_cast<PyTypeObject *>(instanceType), nullptr, nullptr));
1595         self->d->cptr[0] = cptr;
1596         self->d->hasOwnership = hasOwnership;
1597         self->d->validCppObject = 1;
1598         if (shouldRegister) {
1599             BindingManager::instance().registerWrapper(self, cptr);
1600         }
1601     } else {
1602         Py_IncRef(reinterpret_cast<PyObject *>(self));
1603     }
1604     return reinterpret_cast<PyObject *>(self);
1605 }
1606 
destroy(SbkObject * self,void * cppData)1607 void destroy(SbkObject *self, void *cppData)
1608 {
1609     // Skip if this is called with NULL pointer this can happen in derived classes
1610     if (!self)
1611         return;
1612 
1613     // This can be called in c++ side
1614     Shiboken::GilState gil;
1615 
1616     // Remove all references attached to this object
1617     clearReferences(self);
1618 
1619     // Remove the object from parent control
1620 
1621     // Verify if this object has parent
1622     bool hasParent = (self->d->parentInfo && self->d->parentInfo->parent);
1623 
1624     if (self->d->parentInfo) {
1625         // Check for children information and make all invalid if they exists
1626         _destroyParentInfo(self, true);
1627         // If this object has parent then the pyobject can be invalid now, because we remove the last ref after remove from parent
1628     }
1629 
1630     //if !hasParent this object could still alive
1631     if (!hasParent && self->d->containsCppWrapper && !self->d->hasOwnership) {
1632         // Remove extra ref used by c++ object this will case the pyobject destruction
1633         // This can cause the object death
1634         Py_DECREF(reinterpret_cast<PyObject *>(self));
1635     }
1636 
1637     //Python Object is not destroyed yet
1638     if (cppData && Shiboken::BindingManager::instance().hasWrapper(cppData)) {
1639         // Remove from BindingManager
1640         Shiboken::BindingManager::instance().releaseWrapper(self);
1641         self->d->hasOwnership = false;
1642 
1643         // the cpp object instance was deleted
1644         delete[] self->d->cptr;
1645         self->d->cptr = nullptr;
1646     }
1647 
1648     // After this point the object can be death do not use the self pointer bellow
1649 }
1650 
removeParent(SbkObject * child,bool giveOwnershipBack,bool keepReference)1651 void removeParent(SbkObject *child, bool giveOwnershipBack, bool keepReference)
1652 {
1653     ParentInfo *pInfo = child->d->parentInfo;
1654     if (!pInfo || !pInfo->parent) {
1655         if (pInfo && pInfo->hasWrapperRef) {
1656             pInfo->hasWrapperRef = false;
1657         }
1658         return;
1659     }
1660 
1661     ChildrenList &oldBrothers = pInfo->parent->d->parentInfo->children;
1662     // Verify if this child is part of parent list
1663     auto iChild = oldBrothers.find(child);
1664     if (iChild == oldBrothers.end())
1665         return;
1666 
1667     oldBrothers.erase(iChild);
1668 
1669     pInfo->parent = nullptr;
1670 
1671     // This will keep the wrapper reference, will wait for wrapper destruction to remove that
1672     if (keepReference &&
1673         child->d->containsCppWrapper) {
1674         //If have already a extra ref remove this one
1675         if (pInfo->hasWrapperRef)
1676             Py_DECREF(child);
1677         else
1678             pInfo->hasWrapperRef = true;
1679         return;
1680     }
1681 
1682     // Transfer ownership back to Python
1683     child->d->hasOwnership = giveOwnershipBack;
1684 
1685     // Remove parent ref
1686     Py_DECREF(child);
1687 }
1688 
setParent(PyObject * parent,PyObject * child)1689 void setParent(PyObject *parent, PyObject *child)
1690 {
1691     if (!child || child == Py_None || child == parent)
1692         return;
1693 
1694     /*
1695      * setParent is recursive when the child is a native Python sequence, i.e. objects not binded by Shiboken
1696      * like tuple and list.
1697      *
1698      * This "limitation" exists to fix the following problem: A class multiple inherits QObject and QString,
1699      * so if you pass this class to someone that takes the ownership, we CAN'T enter in this if, but hey! QString
1700      * follows the sequence protocol.
1701      */
1702     if (PySequence_Check(child) && !Object::checkType(child)) {
1703         Shiboken::AutoDecRef seq(PySequence_Fast(child, nullptr));
1704         for (Py_ssize_t i = 0, max = PySequence_Size(seq); i < max; ++i)
1705             setParent(parent, PySequence_Fast_GET_ITEM(seq.object(), i));
1706         return;
1707     }
1708 
1709     bool parentIsNull = !parent || parent == Py_None;
1710     auto parent_ = reinterpret_cast<SbkObject *>(parent);
1711     auto child_ = reinterpret_cast<SbkObject *>(child);
1712 
1713     if (!parentIsNull) {
1714         if (!parent_->d->parentInfo)
1715             parent_->d->parentInfo = new ParentInfo;
1716 
1717         // do not re-add a child
1718         if (child_->d->parentInfo && (child_->d->parentInfo->parent == parent_))
1719             return;
1720     }
1721 
1722     ParentInfo *pInfo = child_->d->parentInfo;
1723     bool hasAnotherParent = pInfo && pInfo->parent && pInfo->parent != parent_;
1724 
1725     //Avoid destroy child during reparent operation
1726     Py_INCREF(child);
1727 
1728     // check if we need to remove this child from the old parent
1729     if (parentIsNull || hasAnotherParent)
1730         removeParent(child_);
1731 
1732     // Add the child to the new parent
1733     pInfo = child_->d->parentInfo;
1734     if (!parentIsNull) {
1735         if (!pInfo)
1736             pInfo = child_->d->parentInfo = new ParentInfo;
1737 
1738         pInfo->parent = parent_;
1739         parent_->d->parentInfo->children.insert(child_);
1740 
1741         // Add Parent ref
1742         Py_INCREF(child_);
1743 
1744         // Remove ownership
1745         child_->d->hasOwnership = false;
1746     }
1747 
1748     // Remove previous safe ref
1749     Py_DECREF(child);
1750 }
1751 
deallocData(SbkObject * self,bool cleanup)1752 void deallocData(SbkObject *self, bool cleanup)
1753 {
1754     // Make cleanup if this is not a wrapper otherwise this will be done on wrapper destructor
1755     if(cleanup) {
1756         removeParent(self);
1757 
1758         if (self->d->parentInfo)
1759             _destroyParentInfo(self, true);
1760 
1761         clearReferences(self);
1762     }
1763 
1764     if (self->d->cptr) {
1765         // Remove from BindingManager
1766         Shiboken::BindingManager::instance().releaseWrapper(self);
1767         delete[] self->d->cptr;
1768         self->d->cptr = nullptr;
1769         // delete self->d; PYSIDE-205: wrong!
1770     }
1771     delete self->d; // PYSIDE-205: always delete d.
1772     Py_XDECREF(self->ob_dict);
1773 
1774     // PYSIDE-571: qApp is no longer allocated.
1775     if (PyObject_IS_GC(reinterpret_cast<PyObject *>(self)))
1776         Py_TYPE(self)->tp_free(self);
1777 }
1778 
setTypeUserData(SbkObject * wrapper,void * userData,DeleteUserDataFunc d_func)1779 void setTypeUserData(SbkObject *wrapper, void *userData, DeleteUserDataFunc d_func)
1780 {
1781     SbkObjectTypePrivate *sotp = PepType_SOTP(Py_TYPE(wrapper));
1782     if (sotp->user_data)
1783         sotp->d_func(sotp->user_data);
1784 
1785     sotp->d_func = d_func;
1786     sotp->user_data = userData;
1787 }
1788 
getTypeUserData(SbkObject * wrapper)1789 void *getTypeUserData(SbkObject *wrapper)
1790 {
1791     return PepType_SOTP(Py_TYPE(wrapper))->user_data;
1792 }
1793 
isNone(const PyObject * o)1794 static inline bool isNone(const PyObject *o)
1795 {
1796     return o == nullptr || o == Py_None;
1797 }
1798 
removeRefCountKey(SbkObject * self,const char * key)1799 static void removeRefCountKey(SbkObject *self, const char *key)
1800 {
1801     if (self->d->referredObjects) {
1802         const auto iterPair = self->d->referredObjects->equal_range(key);
1803         if (iterPair.first != iterPair.second) {
1804             decRefPyObjectList(iterPair.first, iterPair.second);
1805             self->d->referredObjects->erase(iterPair.first, iterPair.second);
1806         }
1807     }
1808 }
1809 
keepReference(SbkObject * self,const char * key,PyObject * referredObject,bool append)1810 void keepReference(SbkObject *self, const char *key, PyObject *referredObject, bool append)
1811 {
1812     if (isNone(referredObject)) {
1813         removeRefCountKey(self, key);
1814         return;
1815     }
1816 
1817     if (!self->d->referredObjects) {
1818         self->d->referredObjects =
1819             new Shiboken::RefCountMap{RefCountMap::value_type{key, referredObject}};
1820         Py_INCREF(referredObject);
1821         return;
1822     }
1823 
1824     RefCountMap &refCountMap = *(self->d->referredObjects);
1825     const auto iterPair = refCountMap.equal_range(key);
1826     if (std::any_of(iterPair.first, iterPair.second,
1827                     [referredObject](const RefCountMap::value_type &v) { return v.second == referredObject; })) {
1828         return;
1829     }
1830 
1831     if (!append && iterPair.first != iterPair.second) {
1832         decRefPyObjectList(iterPair.first, iterPair.second);
1833         refCountMap.erase(iterPair.first, iterPair.second);
1834     }
1835 
1836     refCountMap.insert(RefCountMap::value_type{key, referredObject});
1837     Py_INCREF(referredObject);
1838 }
1839 
removeReference(SbkObject * self,const char * key,PyObject * referredObject)1840 void removeReference(SbkObject *self, const char *key, PyObject *referredObject)
1841 {
1842     if (!isNone(referredObject))
1843         removeRefCountKey(self, key);
1844 }
1845 
clearReferences(SbkObject * self)1846 void clearReferences(SbkObject *self)
1847 {
1848     if (!self->d->referredObjects)
1849         return;
1850 
1851     RefCountMap &refCountMap = *(self->d->referredObjects);
1852     for (auto it = refCountMap.begin(), end = refCountMap.end(); it != end; ++it)
1853         Py_DECREF(it->second);
1854     self->d->referredObjects->clear();
1855 }
1856 
info(SbkObject * self)1857 std::string info(SbkObject *self)
1858 {
1859     std::ostringstream s;
1860 
1861     if (self->d && self->d->cptr) {
1862         std::vector<SbkObjectType *> bases;
1863         if (ObjectType::isUserType(Py_TYPE(self)))
1864             bases = getCppBaseClasses(Py_TYPE(self));
1865         else
1866             bases.push_back(reinterpret_cast<SbkObjectType *>(Py_TYPE(self)));
1867 
1868         s << "C++ address....... ";
1869         for (size_t i = 0, size = bases.size(); i < size; ++i) {
1870             auto base = reinterpret_cast<PyTypeObject *>(bases[i]);
1871             s << base->tp_name << '/' << self->d->cptr[i] << ' ';
1872         }
1873         s << "\n";
1874     }
1875     else {
1876         s << "C++ address....... <<Deleted>>\n";
1877     }
1878 
1879     s << "hasOwnership...... " << bool(self->d->hasOwnership) << "\n"
1880          "containsCppWrapper " << self->d->containsCppWrapper << "\n"
1881          "validCppObject.... " << self->d->validCppObject << "\n"
1882          "wasCreatedByPython " << self->d->cppObjectCreated << "\n";
1883 
1884 
1885     if (self->d->parentInfo && self->d->parentInfo->parent) {
1886         s << "parent............ ";
1887         Shiboken::AutoDecRef parent(PyObject_Str(reinterpret_cast<PyObject *>(self->d->parentInfo->parent)));
1888         s << String::toCString(parent) << "\n";
1889     }
1890 
1891     if (self->d->parentInfo && !self->d->parentInfo->children.empty()) {
1892         s << "children.......... ";
1893         for (SbkObject *sbkChild : self->d->parentInfo->children) {
1894             Shiboken::AutoDecRef child(PyObject_Str(reinterpret_cast<PyObject *>(sbkChild)));
1895             s << String::toCString(child) << ' ';
1896         }
1897         s << '\n';
1898     }
1899 
1900     if (self->d->referredObjects && !self->d->referredObjects->empty()) {
1901         Shiboken::RefCountMap &map = *self->d->referredObjects;
1902         s << "referred objects.. ";
1903         std::string lastKey;
1904         for (auto it = map.begin(), end = map.end(); it != end; ++it) {
1905             if (it->first != lastKey) {
1906                 if (!lastKey.empty())
1907                     s << "                   ";
1908                 s << '"' << it->first << "\" => ";
1909                 lastKey = it->first;
1910             }
1911             Shiboken::AutoDecRef obj(PyObject_Str(it->second));
1912             s << String::toCString(obj) << ' ';
1913         }
1914         s << '\n';
1915     }
1916     return s.str();
1917 }
1918 
1919 } // namespace Object
1920 
1921 } // namespace Shiboken
1922