File indexing completed on 2026-09-23 09:21:58
0001
0002
0003
0004
0005
0006 #ifndef QPLUGIN_H
0007 #define QPLUGIN_H
0008
0009 #if 0
0010 #pragma qt_class(QtPlugin)
0011 #endif
0012
0013 #include <QtCore/qobject.h>
0014 #include <QtCore/qpointer.h>
0015 #include <QtCore/qjsonobject.h>
0016
0017 #include <QtCore/q20algorithm.h>
0018
0019 QT_BEGIN_NAMESPACE
0020
0021
0022 inline constexpr unsigned char qPluginArchRequirements()
0023 {
0024 return 0
0025 #ifndef QT_NO_DEBUG
0026 | 1
0027 #endif
0028 #ifdef __AVX2__
0029 | 2
0030 # ifdef __AVX512F__
0031 | 4
0032 # endif
0033 #endif
0034 ;
0035 }
0036
0037 typedef QObject *(*QtPluginInstanceFunction)();
0038 struct QPluginMetaData
0039 {
0040 static constexpr quint8 CurrentMetaDataVersion = 1;
0041 static constexpr char MagicString[] = {
0042 'Q', 'T', 'M', 'E', 'T', 'A', 'D', 'A', 'T', 'A', ' ', '!'
0043 };
0044
0045 template <size_t OSize, typename OO, size_t ISize, typename II>
0046 static constexpr void copy(OO (&out)[OSize], II (&in)[ISize])
0047 {
0048 static_assert(OSize <= ISize, "Output would not be fully initialized");
0049 q20::copy_n(in, OSize, out);
0050 }
0051
0052 static constexpr quint8 archRequirements()
0053 {
0054 quint8 v = 0;
0055 #if defined(__AVX512F__)
0056 v = 4;
0057 #elif defined(__AVX__) || defined(__BMI__) || defined(__BMI2__) || defined(__MOVBE__)
0058 v = 3;
0059 #elif defined(__SSE3__)
0060 v = 2;
0061 #elif defined(__SSE__) || defined(__MMX___)
0062 v = 1;
0063 #endif
0064 #ifndef QT_NO_DEBUG
0065 v |= 0x80;
0066 #endif
0067 return v;
0068 }
0069
0070 struct Header {
0071 quint8 version = CurrentMetaDataVersion;
0072 quint8 qt_major_version = QT_VERSION_MAJOR;
0073 quint8 qt_minor_version = QT_VERSION_MINOR;
0074 quint8 plugin_arch_requirements = archRequirements();
0075 };
0076 static_assert(alignof(Header) == 1, "Alignment of header incorrect with this compiler");
0077
0078 struct MagicHeader {
0079 char magic[sizeof(QPluginMetaData::MagicString)] = {};
0080 constexpr MagicHeader() { copy(magic, QPluginMetaData::MagicString); }
0081 Header header = {};
0082 };
0083 static_assert(alignof(MagicHeader) == 1, "Alignment of header incorrect with this compiler");
0084
0085 struct ElfNoteHeader {
0086 static constexpr quint32 NoteType = 0x74510001;
0087 static constexpr char NoteName[] = "qt-project!";
0088
0089
0090 quint32 n_namesz = sizeof(name);
0091 quint32 n_descsz;
0092 quint32 n_type = NoteType;
0093 char name[sizeof(NoteName)] = {};
0094
0095
0096 alignas(void *)
0097 Header header = {};
0098 constexpr ElfNoteHeader(quint32 payloadSize) : n_descsz(sizeof(header) + payloadSize)
0099 { QPluginMetaData::copy(name, NoteName); }
0100 };
0101 static_assert(alignof(ElfNoteHeader) == alignof(void*), "Alignment of header incorrect with this compiler");
0102 static_assert((sizeof(ElfNoteHeader::name) % 4) == 0, "ELF note name length not a multiple of 4");
0103
0104 const void *data;
0105 size_t size;
0106 };
0107 typedef QPluginMetaData (*QtPluginMetaDataFunction)();
0108
0109
0110 struct Q_CORE_EXPORT QStaticPlugin
0111 {
0112 public:
0113 constexpr QStaticPlugin(QtPluginInstanceFunction i, QtPluginMetaDataFunction m)
0114 : instance(i), rawMetaDataSize(m().size), rawMetaData(m().data)
0115 {}
0116 QtPluginInstanceFunction instance;
0117 QJsonObject metaData() const;
0118
0119 private:
0120 qsizetype rawMetaDataSize;
0121 const void *rawMetaData;
0122 friend class QFactoryLoader;
0123 };
0124 Q_DECLARE_TYPEINFO(QStaticPlugin, Q_PRIMITIVE_TYPE);
0125
0126 void Q_CORE_EXPORT qRegisterStaticPluginFunction(QStaticPlugin staticPlugin);
0127
0128 #if defined(Q_OF_ELF) || (defined(Q_OS_WIN) && (defined (Q_CC_GNU) || defined(Q_CC_CLANG)))
0129 # define QT_PLUGIN_METADATA_SECTION \
0130 __attribute__ ((section (".qtmetadata"))) __attribute__((used))
0131 #elif defined(Q_OS_DARWIN)
0132 # define QT_PLUGIN_METADATA_SECTION \
0133 __attribute__ ((section ("__TEXT,qtmetadata"))) __attribute__((used))
0134 #elif defined(Q_CC_MSVC)
0135
0136 #pragma section(".qtmetadata",read,shared)
0137 # define QT_PLUGIN_METADATA_SECTION \
0138 __declspec(allocate(".qtmetadata"))
0139 #else
0140 # define QT_PLUGIN_METADATA_SECTION
0141 #endif
0142
0143
0144 template <auto (&PluginMetaData)> class QPluginMetaDataV2
0145 {
0146 struct ElfNotePayload : QPluginMetaData::ElfNoteHeader {
0147 static constexpr size_t HeaderOffset = offsetof(QPluginMetaData::ElfNoteHeader, header);
0148 quint8 payload[sizeof(PluginMetaData)] = {};
0149 constexpr ElfNotePayload() : ElfNoteHeader(sizeof(PluginMetaData))
0150 { QPluginMetaData::copy(payload, PluginMetaData); }
0151 };
0152
0153 struct RegularPayload : QPluginMetaData::MagicHeader {
0154 static constexpr size_t HeaderOffset = offsetof(QPluginMetaData::MagicHeader, header);
0155 quint8 payload[sizeof(PluginMetaData)] = {};
0156 constexpr RegularPayload() { QPluginMetaData::copy(payload, PluginMetaData); }
0157 };
0158
0159 struct StaticPayload {
0160 static constexpr size_t HeaderOffset = 0;
0161 QPluginMetaData::Header header = {};
0162 quint8 payload[sizeof(PluginMetaData)] = {};
0163 constexpr StaticPayload() { QPluginMetaData::copy(payload, PluginMetaData); }
0164 };
0165
0166 #if defined(QT_STATICPLUGIN)
0167 # define QT_PLUGIN_METADATAV2_SECTION
0168 using Payload = StaticPayload;
0169 #elif defined(Q_OF_ELF)
0170 # ifdef Q_CC_CLANG
0171 # define QT_PLUGIN_METADATAV2_SECTION \
0172 __attribute__((section(".note.qt.metadata"), used, aligned(alignof(void *)), \
0173 no_sanitize("address")))
0174 # else
0175 # define QT_PLUGIN_METADATAV2_SECTION \
0176 __attribute__((section(".note.qt.metadata"), used, aligned(alignof(void *))))
0177 # endif
0178 using Payload = ElfNotePayload;
0179 #else
0180 # define QT_PLUGIN_METADATAV2_SECTION QT_PLUGIN_METADATA_SECTION
0181 using Payload = RegularPayload;
0182 #endif
0183
0184 Payload payload = {};
0185
0186 public:
0187 operator QPluginMetaData() const
0188 {
0189 Q_ASSERT(reinterpret_cast<const char *>(&payload) + Payload::HeaderOffset ==
0190 reinterpret_cast<const char *>(&payload.header));
0191 return { &payload.header, sizeof(payload) - Payload::HeaderOffset };
0192 }
0193 };
0194
0195 #define Q_IMPORT_PLUGIN(PLUGIN) \
0196 extern const QT_PREPEND_NAMESPACE(QStaticPlugin) QT_MANGLE_NAMESPACE(qt_static_plugin_##PLUGIN)(); \
0197 namespace { \
0198 struct Static##PLUGIN##PluginInstance { \
0199 Static##PLUGIN##PluginInstance() { \
0200 qRegisterStaticPluginFunction(QT_MANGLE_NAMESPACE(qt_static_plugin_##PLUGIN)()); \
0201 } \
0202 }; \
0203 } \
0204 \
0205 static Static##PLUGIN##PluginInstance static##PLUGIN##Instance; \
0206
0207 #if defined(QT_PLUGIN_RESOURCE_INIT_FUNCTION)
0208 # define QT_PLUGIN_RESOURCE_INIT \
0209 extern void QT_PLUGIN_RESOURCE_INIT_FUNCTION(); \
0210 QT_PLUGIN_RESOURCE_INIT_FUNCTION();
0211 #else
0212 # define QT_PLUGIN_RESOURCE_INIT
0213 #endif
0214
0215 #define Q_PLUGIN_INSTANCE(IMPLEMENTATION) \
0216 { \
0217 static QT_PREPEND_NAMESPACE(QPointer)<QT_PREPEND_NAMESPACE(QObject)> _instance; \
0218 if (!_instance) { \
0219 QT_PLUGIN_RESOURCE_INIT \
0220 _instance = new IMPLEMENTATION; \
0221 } \
0222 return _instance; \
0223 }
0224
0225 #if defined(QT_STATICPLUGIN)
0226 # define QT_MOC_EXPORT_PLUGIN_COMMON(PLUGINCLASS, MANGLEDNAME) \
0227 static QT_PREPEND_NAMESPACE(QObject) *qt_plugin_instance_##MANGLEDNAME() \
0228 Q_PLUGIN_INSTANCE(PLUGINCLASS) \
0229 const QT_PREPEND_NAMESPACE(QStaticPlugin) QT_MANGLE_NAMESPACE(qt_static_plugin_##MANGLEDNAME)() \
0230 { return { qt_plugin_instance_##MANGLEDNAME, qt_plugin_query_metadata_##MANGLEDNAME}; } \
0231
0232
0233 # define QT_MOC_EXPORT_PLUGIN(PLUGINCLASS, PLUGINCLASSNAME) \
0234 static QPluginMetaData qt_plugin_query_metadata_##PLUGINCLASSNAME() \
0235 { return { qt_pluginMetaData_##PLUGINCLASSNAME, sizeof qt_pluginMetaData_##PLUGINCLASSNAME }; } \
0236 QT_MOC_EXPORT_PLUGIN_COMMON(PLUGINCLASS, PLUGINCLASSNAME)
0237
0238 # define QT_MOC_EXPORT_PLUGIN_V2(PLUGINCLASS, MANGLEDNAME, MD) \
0239 static QT_PREPEND_NAMESPACE(QPluginMetaData) qt_plugin_query_metadata_##MANGLEDNAME() \
0240 { static constexpr QPluginMetaDataV2<MD> md{}; return md; } \
0241 QT_MOC_EXPORT_PLUGIN_COMMON(PLUGINCLASS, MANGLEDNAME)
0242 #else
0243 # define QT_MOC_EXPORT_PLUGIN_COMMON(PLUGINCLASS, MANGLEDNAME) \
0244 extern "C" Q_DECL_EXPORT QT_PREPEND_NAMESPACE(QObject) *qt_plugin_instance() \
0245 Q_PLUGIN_INSTANCE(PLUGINCLASS) \
0246
0247
0248 # define QT_MOC_EXPORT_PLUGIN(PLUGINCLASS, PLUGINCLASSNAME) \
0249 extern "C" Q_DECL_EXPORT \
0250 QPluginMetaData qt_plugin_query_metadata() \
0251 { return { qt_pluginMetaData_##PLUGINCLASSNAME, sizeof qt_pluginMetaData_##PLUGINCLASSNAME }; } \
0252 QT_MOC_EXPORT_PLUGIN_COMMON(PLUGINCLASS, PLUGINCLASSNAME)
0253
0254 # define QT_MOC_EXPORT_PLUGIN_V2(PLUGINCLASS, MANGLEDNAME, MD) \
0255 extern "C" Q_DECL_EXPORT QT_PREPEND_NAMESPACE(QPluginMetaData) qt_plugin_query_metadata_v2()\
0256 { static constexpr QT_PLUGIN_METADATAV2_SECTION QPluginMetaDataV2<MD> md{}; return md; } \
0257 QT_MOC_EXPORT_PLUGIN_COMMON(PLUGINCLASS, MANGLEDNAME)
0258 #endif
0259
0260 #define Q_EXPORT_PLUGIN(PLUGIN) \
0261 Q_EXPORT_PLUGIN2(PLUGIN, PLUGIN)
0262 # define Q_EXPORT_PLUGIN2(PLUGIN, PLUGINCLASS) \
0263 static_assert(false, "Old plugin system used")
0264
0265 # define Q_EXPORT_STATIC_PLUGIN2(PLUGIN, PLUGINCLASS) \
0266 static_assert(false, "Old plugin system used")
0267
0268
0269 QT_END_NAMESPACE
0270
0271 #endif