1// Copyright (C) 2024 The Qt Company Ltd.
2// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
3
4#ifndef Q_SYMBOLSRESOLVEUTILS
5#define Q_SYMBOLSRESOLVEUTILS
6
7#include <QtCore/qlibrary.h>
8#include <QtMultimedia/qtmultimediaexports.h>
9#include <tuple>
10#include <memory>
11
12//
13// W A R N I N G
14// -------------
15//
16// This file is not part of the Qt API. It exists purely as an
17// implementation detail. This header file may change from version to
18// version without notice, or even be removed.
19//
20// We mean it.
21//
22
23QT_BEGIN_NAMESPACE
24
25constexpr bool areVersionsEqual(const char lhs[], const char rhs[])
26{
27 int i = 0;
28 for (; lhs[i] && rhs[i]; ++i)
29 if (lhs[i] != rhs[i])
30 return false;
31 return lhs[i] == rhs[i];
32}
33
34constexpr bool areVersionsEqual(const char lhs[], int rhsInt)
35{
36 int lhsInt = 0;
37 for (int i = 0; lhs[i]; ++i) {
38 if (lhs[i] < '0' || lhs[i] > '9')
39 return false;
40
41 lhsInt *= 10;
42 lhsInt += lhs[i] - '0';
43 }
44
45 return lhsInt == rhsInt;
46}
47
48
49template <typename T>
50struct DefaultReturn
51{
52 template <typename... Arg>
53 T operator()(Arg &&...) { return val; }
54 T val;
55};
56
57template <>
58struct DefaultReturn<void>
59{
60 template <typename... Arg>
61 void operator()(Arg &&...) { }
62};
63
64template <typename...>
65struct FuncInfo;
66
67template <typename R, typename... A>
68struct FuncInfo<R(A...)>
69{
70 using Return = R;
71 using Args = std::tuple<A...>;
72};
73
74class Q_MULTIMEDIA_EXPORT SymbolsResolver
75{
76public:
77 using LibraryLoader = std::unique_ptr<QLibrary> (*)();
78 static bool isLazyLoadEnabled();
79 bool isLoaded() const { return m_library != nullptr; }
80
81 ~SymbolsResolver();
82protected:
83 SymbolsResolver(const char *libLoggingName, LibraryLoader loader);
84
85 SymbolsResolver(const char *libName, const char *version = "",
86 const char *libLoggingName = nullptr);
87
88 QFunctionPointer initOptionalFunction(const char *name);
89 QFunctionPointer initFunction(const char *name);
90
91 struct SymbolsMarker {};
92 void checkLibrariesLoaded(SymbolsMarker *begin, SymbolsMarker *end);
93
94private:
95 const char *m_libLoggingName;
96 std::unique_ptr<QLibrary> m_library;
97};
98
99
100QT_END_NAMESPACE
101
102// clang-format off
103
104#define CHECK_VERSIONS(Name, NeededSoversion, DetectedVersion) \
105 static_assert(areVersionsEqual(NeededSoversion, DetectedVersion), \
106 "Configuartion error: misleading " Name " versions!")
107
108#define BEGIN_INIT_FUNCS(...) \
109 QT_USE_NAMESPACE \
110 namespace { \
111 class SymbolsResolverImpl : public SymbolsResolver { \
112 public: \
113 SymbolsResolverImpl() : SymbolsResolver(__VA_ARGS__) \
114 { checkLibrariesLoaded(&symbolsBegin, &symbolsEnd); } \
115 static const SymbolsResolverImpl& instance() \
116 { static const SymbolsResolverImpl instance; return instance; } \
117 SymbolsMarker symbolsBegin;
118
119#define INIT_FUNC(F) QFunctionPointer F = initFunction(#F);
120#define INIT_OPT_FUNC(F) QFunctionPointer F = initOptionalFunction(#F);
121
122#define END_INIT_FUNCS() \
123 SymbolsMarker symbolsEnd; \
124 }; \
125 [[maybe_unused]] static const auto *instantResolver = \
126 SymbolsResolver::isLazyLoadEnabled() ? &SymbolsResolverImpl::instance() : nullptr; \
127 }
128
129
130#ifdef Q_EXPORT_STUB_SYMBOLS
131#define EXPORT_FUNC Q_MULTIMEDIA_EXPORT
132#else
133#define EXPORT_FUNC
134#endif
135
136#define DEFINE_FUNC_IMPL(F, Vars, TypesWithVars, ReturnFunc) \
137 using F##_ReturnType = FuncInfo<decltype(F)>::Return; \
138 extern "C" EXPORT_FUNC [[maybe_unused]] F##_ReturnType F(TypesWithVars(F)) { \
139 using F##_Type = F##_ReturnType (*)(TypesWithVars(F)); \
140 const auto f = SymbolsResolverImpl::instance().F; \
141 return f ? (reinterpret_cast<F##_Type>(f))(Vars()) : ReturnFunc(); \
142 }
143
144
145#define VAR(I) a##I
146#define VARS0()
147#define VARS1() VAR(0)
148#define VARS2() VARS1(), VAR(1)
149#define VARS3() VARS2(), VAR(2)
150#define VARS4() VARS3(), VAR(3)
151#define VARS5() VARS4(), VAR(4)
152#define VARS6() VARS5(), VAR(5)
153#define VARS7() VARS6(), VAR(6)
154#define VARS8() VARS7(), VAR(7)
155#define VARS9() VARS8(), VAR(8)
156#define VARS10() VARS9(), VAR(9)
157#define VARS11() VARS10(), VAR(10)
158
159#define TYPE_WITH_VAR(F, I) std::tuple_element_t<I, FuncInfo<decltype(F)>::Args> VAR(I)
160#define TYPES_WITH_VARS0(F)
161#define TYPES_WITH_VARS1(F) TYPE_WITH_VAR(F, 0)
162#define TYPES_WITH_VARS2(F) TYPES_WITH_VARS1(F), TYPE_WITH_VAR(F, 1)
163#define TYPES_WITH_VARS3(F) TYPES_WITH_VARS2(F), TYPE_WITH_VAR(F, 2)
164#define TYPES_WITH_VARS4(F) TYPES_WITH_VARS3(F), TYPE_WITH_VAR(F, 3)
165#define TYPES_WITH_VARS5(F) TYPES_WITH_VARS4(F), TYPE_WITH_VAR(F, 4)
166#define TYPES_WITH_VARS6(F) TYPES_WITH_VARS5(F), TYPE_WITH_VAR(F, 5)
167#define TYPES_WITH_VARS7(F) TYPES_WITH_VARS6(F), TYPE_WITH_VAR(F, 6)
168#define TYPES_WITH_VARS8(F) TYPES_WITH_VARS7(F), TYPE_WITH_VAR(F, 7)
169#define TYPES_WITH_VARS9(F) TYPES_WITH_VARS8(F), TYPE_WITH_VAR(F, 8)
170#define TYPES_WITH_VARS10(F) TYPES_WITH_VARS9(F), TYPE_WITH_VAR(F, 9)
171#define TYPES_WITH_VARS11(F) TYPES_WITH_VARS10(F), TYPE_WITH_VAR(F, 10)
172
173
174#define RET(F, ...) DefaultReturn<FuncInfo<decltype(F)>::Return>{__VA_ARGS__}
175
176#define DEFINE_FUNC(F, ArgsCount, /*Return value*/...) \
177 DEFINE_FUNC_IMPL(F, VARS##ArgsCount, TYPES_WITH_VARS##ArgsCount, RET(F, __VA_ARGS__));
178
179#define DEFINE_IS_LOADED_CHECKER(FuncName) \
180QT_BEGIN_NAMESPACE \
181bool FuncName() { return SymbolsResolverImpl::instance().isLoaded(); } \
182QT_END_NAMESPACE
183
184#define DECLARE_IS_LOADED_CHECKER(FuncName) \
185QT_BEGIN_NAMESPACE \
186bool FuncName(); \
187QT_END_NAMESPACE
188
189// clang-format on
190
191#endif // Q_SYMBOLSRESOLVEUTILS
192

Provided by KDAB

Privacy Policy
Learn to use CMake with our Intro Training
Find out more

source code of qtmultimedia/src/multimedia/qsymbolsresolveutils_p.h