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