aboutsummaryrefslogtreecommitdiffstats
path: root/sources/pyside6/libpysideremoteobjects/pysidedynamiccommon_p.h
diff options
context:
space:
mode:
Diffstat (limited to 'sources/pyside6/libpysideremoteobjects/pysidedynamiccommon_p.h')
-rw-r--r--sources/pyside6/libpysideremoteobjects/pysidedynamiccommon_p.h89
1 files changed, 89 insertions, 0 deletions
diff --git a/sources/pyside6/libpysideremoteobjects/pysidedynamiccommon_p.h b/sources/pyside6/libpysideremoteobjects/pysidedynamiccommon_p.h
new file mode 100644
index 000000000..1e9f8d55a
--- /dev/null
+++ b/sources/pyside6/libpysideremoteobjects/pysidedynamiccommon_p.h
@@ -0,0 +1,89 @@
+// 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.
+
+static int capsule_count = 0;
+
+static PyObject *get_capsule_count()
+{
+ return PyLong_FromLong(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