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