1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
|
// Copyright (C) 2025 Ford Motor Company
// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
#ifndef PYSIDE_DYNAMIC_COMMON_P_H
#define PYSIDE_DYNAMIC_COMMON_P_H
#include <sbkconverter.h>
#include <QtCore/qlist.h>
#include <QtCore/qvariant.h>
#include <QtCore/qmetatype.h>
PyObject *toPython(const QVariant &variant);
int create_managed_py_enums(PyObject *self, QMetaObject *meta);
PyObject *DynamicType_get_enum(PyObject *self, PyObject *name);
// Data for dynamically created property handlers
struct PropertyCapsule
{
QByteArray name;
int propertyIndex; // meta->indexOfProperty() - including offset
int indexInObject; // Index minus offset for indexing into QVariantList
};
// Data for dynamically created method handlers
struct MethodCapsule
{
QByteArray name;
int methodIndex;
QList<QMetaType> argumentTypes;
QMetaType returnType; // meta->indexOfMethod() - including offset
};
// These functions are used to create a PyCapsule holding a pointer to a C++
// object, which is set as an attribute on a Python type. When the Python
// type is garbage collected, the type's attributes are as well, resulting in
// the capsule's cleanup running to delete the pointer. This won't be as
// efficient as a custom tp_free on the type, but it's easier to manage.
// And it only runs when as all references to the type (and all instances) are
// released, so it won't be used frequently.
extern int capsule_count;
template <typename T>
void Capsule_destructor(PyObject *capsule)
{
capsule_count--;
T pointer = static_cast<T>(PyCapsule_GetPointer(capsule, nullptr));
delete pointer;
pointer = nullptr;
}
template <>
inline void Capsule_destructor<SbkConverter *>(PyObject *capsule)
{
capsule_count--;
SbkConverter *pointer = static_cast<SbkConverter *>(PyCapsule_GetPointer(capsule, nullptr));
Shiboken::Conversions::deleteConverter(pointer);
pointer = nullptr;
}
template <typename T>
int set_cleanup_capsule_attr_for_pointer(PyTypeObject *type, const char *name, T pointer)
{
static_assert(std::is_pointer<T>::value, "T must be a pointer type");
if (!pointer) {
PyErr_SetString(PyExc_RuntimeError, "Pointer is null");
return -1;
}
auto capsule = PyCapsule_New(pointer, nullptr, Capsule_destructor<T>);
if (!capsule)
return -1; // Propagate the error
if (PyObject_SetAttrString(reinterpret_cast<PyObject *>(type), name, capsule) < 0)
return -1; // Propagate the error
Py_DECREF(capsule);
capsule_count++;
return 0;
}
#endif // PYSIDE_DYNAMIC_COMMON_P_H
|