Type erase native interfaces via string instead of typeid
The latter forces users to build with RTTI enabled, as the typeid use is in our public headers. Surprisingly this is also the case even without instantiating the relevant template. Change-Id: Icd18a2b85b250e0b77960797e5c43b7eaf9bd891 Reviewed-by: Friedemann Kleint <Friedemann.Kleint@qt.io> Reviewed-by: Fabian Kosmale <fabian.kosmale@qt.io>
This commit is contained in:
parent
e253a30238
commit
486b7a8f8a
@ -43,8 +43,6 @@
|
||||
#include <QtCore/qglobal.h>
|
||||
#include <QtCore/qloggingcategory.h>
|
||||
|
||||
#include <typeinfo>
|
||||
|
||||
#ifndef QT_STATIC
|
||||
# define Q_NATIVE_INTERFACE_EXPORT Q_DECL_EXPORT
|
||||
# define Q_NATIVE_INTERFACE_IMPORT Q_DECL_IMPORT
|
||||
@ -65,6 +63,7 @@ QT_BEGIN_NAMESPACE
|
||||
virtual ~NativeInterface(); \
|
||||
struct TypeInfo { \
|
||||
using baseType = BaseType; \
|
||||
static constexpr char const *name = QT_STRINGIFY(NativeInterface); \
|
||||
static constexpr int revision = Revision; \
|
||||
}; \
|
||||
public: \
|
||||
@ -85,6 +84,7 @@ namespace QNativeInterface::Private {
|
||||
template <typename NativeInterface>
|
||||
struct TypeInfo : private NativeInterface
|
||||
{
|
||||
static constexpr char const *name() { return NativeInterface::TypeInfo::name; }
|
||||
static constexpr int revision() { return NativeInterface::TypeInfo::revision; }
|
||||
|
||||
template<typename BaseType>
|
||||
@ -93,7 +93,7 @@ namespace QNativeInterface::Private {
|
||||
};
|
||||
|
||||
template <typename T>
|
||||
Q_NATIVE_INTERFACE_IMPORT void *resolveInterface(const T *that, const std::type_info &type, int revision);
|
||||
Q_NATIVE_INTERFACE_IMPORT void *resolveInterface(const T *that, const char *name, int revision);
|
||||
|
||||
Q_CORE_EXPORT Q_DECLARE_LOGGING_CATEGORY(lcNativeInterface)
|
||||
}
|
||||
@ -104,10 +104,12 @@ namespace QNativeInterface::Private {
|
||||
I *nativeInterface() const \
|
||||
{ \
|
||||
using T = std::decay_t<decltype(*this)>; \
|
||||
static_assert(QNativeInterface::Private::TypeInfo<I>::template isCompatibleWith<T>, \
|
||||
using NativeInterface = QNativeInterface::Private::TypeInfo<I>; \
|
||||
static_assert(NativeInterface::template isCompatibleWith<T>, \
|
||||
"T::nativeInterface<I>() requires that native interface I is compatible with T"); \
|
||||
\
|
||||
return static_cast<I*>(QNativeInterface::Private::resolveInterface(this, typeid(I), QNativeInterface::Private::TypeInfo<I>::revision())); \
|
||||
return static_cast<I*>(QNativeInterface::Private::resolveInterface(this, \
|
||||
NativeInterface::name(), NativeInterface::revision())); \
|
||||
}
|
||||
|
||||
// Provides a definition for the interface destructor
|
||||
@ -119,17 +121,17 @@ namespace QNativeInterface::Private {
|
||||
|
||||
#define QT_NATIVE_INTERFACE_RETURN_IF(NativeInterface, baseType) \
|
||||
using QNativeInterface::Private::lcNativeInterface; \
|
||||
qCDebug(lcNativeInterface, "Comparing requested type id %s with available %s", \
|
||||
type.name(), typeid(NativeInterface).name()); \
|
||||
if (type == typeid(NativeInterface)) { \
|
||||
qCDebug(lcNativeInterface, "Match for type id %s. Comparing revisions (requested %d / available %d)", \
|
||||
type.name(), revision, TypeInfo<NativeInterface>::revision()); \
|
||||
qCDebug(lcNativeInterface, "Comparing requested interface name %s with available %s", \
|
||||
name, TypeInfo<NativeInterface>::name()); \
|
||||
if (qstrcmp(name, TypeInfo<NativeInterface>::name()) == 0) { \
|
||||
qCDebug(lcNativeInterface, "Match for interface %s. Comparing revisions (requested %d / available %d)", \
|
||||
name, revision, TypeInfo<NativeInterface>::revision()); \
|
||||
if (revision == TypeInfo<NativeInterface>::revision()) { \
|
||||
qCDebug(lcNativeInterface) << "Full match. Returning dynamic cast of" << baseType; \
|
||||
return dynamic_cast<NativeInterface*>(baseType); \
|
||||
} else { \
|
||||
qCWarning(lcNativeInterface, "Native interface revision mismatch (requested %d / available %d) for interface %s", \
|
||||
revision, TypeInfo<NativeInterface>::revision(), type.name()); \
|
||||
revision, TypeInfo<NativeInterface>::revision(), name); \
|
||||
return nullptr; \
|
||||
} \
|
||||
}
|
||||
|
@ -3241,9 +3241,9 @@ QCoreApplication::checkPermission(const QString &permission)
|
||||
#endif // future && QT_NO_QOBJECT
|
||||
|
||||
template <>
|
||||
Q_NATIVE_INTERFACE_EXPORT void *QNativeInterface::Private::resolveInterface(const QCoreApplication *that, const std::type_info &type, int revision)
|
||||
Q_NATIVE_INTERFACE_EXPORT void *QNativeInterface::Private::resolveInterface(const QCoreApplication *that, const char *name, int revision)
|
||||
{
|
||||
Q_UNUSED(that); Q_UNUSED(type); Q_UNUSED(revision);
|
||||
Q_UNUSED(that); Q_UNUSED(name); Q_UNUSED(revision);
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
|
@ -4197,7 +4197,7 @@ QInputDeviceManager *QGuiApplicationPrivate::inputDeviceManager()
|
||||
}
|
||||
|
||||
template <>
|
||||
Q_NATIVE_INTERFACE_EXPORT void *QNativeInterface::Private::resolveInterface(const QGuiApplication *that, const std::type_info &type, int revision)
|
||||
Q_NATIVE_INTERFACE_EXPORT void *QNativeInterface::Private::resolveInterface(const QGuiApplication *that, const char *name, int revision)
|
||||
{
|
||||
using namespace QNativeInterface::Private;
|
||||
|
||||
@ -4208,7 +4208,7 @@ Q_NATIVE_INTERFACE_EXPORT void *QNativeInterface::Private::resolveInterface(cons
|
||||
QT_NATIVE_INTERFACE_RETURN_IF(QWindowsApplication, platformIntegration);
|
||||
#endif
|
||||
|
||||
return resolveInterface<QCoreApplication>(that, type, revision);
|
||||
return resolveInterface<QCoreApplication>(that, name, revision);
|
||||
}
|
||||
|
||||
#include "moc_qguiapplication.cpp"
|
||||
|
@ -136,9 +136,9 @@ QList<int> QKeyMapperPrivate::possibleKeys(QKeyEvent *e)
|
||||
}
|
||||
|
||||
template <>
|
||||
Q_NATIVE_INTERFACE_EXPORT void *QNativeInterface::Private::resolveInterface(const QKeyMapper *that, const std::type_info &type, int revision)
|
||||
Q_NATIVE_INTERFACE_EXPORT void *QNativeInterface::Private::resolveInterface(const QKeyMapper *that, const char *name, int revision)
|
||||
{
|
||||
Q_UNUSED(that); Q_UNUSED(type); Q_UNUSED(revision);
|
||||
Q_UNUSED(that); Q_UNUSED(name); Q_UNUSED(revision);
|
||||
using namespace QNativeInterface::Private;
|
||||
|
||||
#if QT_CONFIG(evdev)
|
||||
|
@ -372,9 +372,9 @@ QPlatformSurface *QOffscreenSurface::surfaceHandle() const
|
||||
using namespace QNativeInterface;
|
||||
|
||||
template <>
|
||||
Q_NATIVE_INTERFACE_EXPORT void *QNativeInterface::Private::resolveInterface(const QOffscreenSurface *that, const std::type_info &type, int revision)
|
||||
Q_NATIVE_INTERFACE_EXPORT void *QNativeInterface::Private::resolveInterface(const QOffscreenSurface *that, const char *name, int revision)
|
||||
{
|
||||
Q_UNUSED(that); Q_UNUSED(type); Q_UNUSED(revision);
|
||||
Q_UNUSED(that); Q_UNUSED(name); Q_UNUSED(revision);
|
||||
|
||||
auto *surfacePrivate = QOffscreenSurfacePrivate::get(const_cast<QOffscreenSurface*>(that));
|
||||
Q_UNUSED(surfacePrivate);
|
||||
|
@ -1312,9 +1312,9 @@ QDebug operator<<(QDebug debug, const QOpenGLContextGroup *cg)
|
||||
using namespace QNativeInterface;
|
||||
|
||||
template <>
|
||||
Q_NATIVE_INTERFACE_EXPORT void *QNativeInterface::Private::resolveInterface(const QOpenGLContext *that, const std::type_info &type, int revision)
|
||||
Q_NATIVE_INTERFACE_EXPORT void *QNativeInterface::Private::resolveInterface(const QOpenGLContext *that, const char *name, int revision)
|
||||
{
|
||||
Q_UNUSED(that); Q_UNUSED(type); Q_UNUSED(revision);
|
||||
Q_UNUSED(that); Q_UNUSED(name); Q_UNUSED(revision);
|
||||
|
||||
auto *platformContext = that->handle();
|
||||
Q_UNUSED(platformContext);
|
||||
|
@ -4101,9 +4101,9 @@ QPixmap QApplicationPrivate::applyQIconStyleHelper(QIcon::Mode mode, const QPixm
|
||||
}
|
||||
|
||||
template <>
|
||||
Q_NATIVE_INTERFACE_EXPORT void *QNativeInterface::Private::resolveInterface(const QApplication *that, const std::type_info &type, int revision)
|
||||
Q_NATIVE_INTERFACE_EXPORT void *QNativeInterface::Private::resolveInterface(const QApplication *that, const char *name, int revision)
|
||||
{
|
||||
return resolveInterface<QGuiApplication>(that, type, revision);
|
||||
return resolveInterface<QGuiApplication>(that, name, revision);
|
||||
}
|
||||
|
||||
QT_END_NAMESPACE
|
||||
|
Loading…
x
Reference in New Issue
Block a user