pysidedynamiccommon_p.h 2.6 KB

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