ReXGlue SDK
Loading...
Searching...
No Matches
module.h
Go to the documentation of this file.
1
11
12#pragma once
13
14#include <array>
15#include <cstddef>
16#include <span>
17#include <string_view>
18#include <type_traits>
19#include <vector>
20
21#include <rex/platform.h>
22#include <rex/result.h>
23#include <rex/types.h>
24#include <rex/utility.h>
25#include <rex/version.h>
26
27namespace rex {
28
29namespace detail {
30
31template <typename T>
32constexpr const char* FunctionSignature() {
33#if defined(__clang__) || defined(__GNUC__)
34 return __PRETTY_FUNCTION__;
35#else
36 return __FUNCSIG__;
37#endif
38}
39
40template <typename T>
41constexpr std::string_view ExtractTypeName() {
42 std::string_view signature = FunctionSignature<T>();
43#if defined(__clang__) || defined(__GNUC__)
44 constexpr std::string_view kMarker = "T = ";
45 const size_t begin = signature.find(kMarker) + kMarker.size();
46 const size_t end = signature.find_first_of(";]", begin);
47#else
48 constexpr std::string_view kMarker = "FunctionSignature<";
49 const size_t begin = signature.find(kMarker) + kMarker.size();
50 const size_t end = signature.rfind(">(");
51#endif
52 std::string_view name = signature.substr(begin, end - begin);
53 for (std::string_view prefix :
54 {std::string_view("class "), std::string_view("struct "), std::string_view("enum ")}) {
55 if (name.starts_with(prefix)) {
56 name.remove_prefix(prefix.size());
57 }
58 }
59 return name;
60}
61
62template <typename T>
63inline constexpr auto kTypeNameChars = [] {
64 constexpr std::string_view kName = ExtractTypeName<T>();
65 std::array<char, kName.size() + 1> chars{};
66 for (size_t i = 0; i < kName.size(); ++i) {
67 chars[i] = kName[i];
68 }
69 return chars;
70}();
71
73template <typename T>
74inline constexpr const char* kTypeName = kTypeNameChars<T>.data();
75
76} // namespace detail
77
80 const char* name;
81 u32 version;
82 bool is_private = false;
83};
84
86class IInterface : NonCopyable {
87 public:
88 virtual ~IInterface() = default;
89};
90
97#define REX_DETAIL_ID(x) x
98
114#define REX_DECLARE_INTERFACE(Name, version) \
115 class REX_DETAIL_ID(Name) : public ::rex::IInterface { \
116 public: \
117 static constexpr ::rex::InterfaceType kInterface{::rex::detail::kTypeName<Name>, version};
118
125#define REX_DECLARE_PRIVATE_INTERFACE(Name, version) \
126 class REX_DETAIL_ID(Name) : public ::rex::IInterface { \
127 public: \
128 static constexpr ::rex::InterfaceType kInterface{::rex::detail::kTypeName<Name>, version, true};
129
132 public:
133 virtual ~IInterfaceFactory() = default;
134
139 virtual IInterface* Find(std::string_view name, u32 version) = 0;
140
147 virtual std::vector<IInterface*> FindAll(std::string_view name, u32 version) = 0;
148
155 template <typename T>
156 T* Get() {
157 return static_cast<T*>(Find(T::kInterface.name, T::kInterface.version));
158 }
159
166 template <typename T>
167 std::vector<T*> FindAll() {
168 std::vector<T*> found;
169 for (IInterface* iface : FindAll(T::kInterface.name, T::kInterface.version)) {
170 found.push_back(static_cast<T*>(iface));
171 }
172 return found;
173 }
174};
175
178 virtual std::string_view GetName() const = 0;
179
185 virtual std::span<const InterfaceType> GetRequiredInterfaces() const { return {}; }
186
192 virtual std::span<const InterfaceType> GetServedInterfaces() const { return {}; }
193
201 [[nodiscard]] virtual Result<void> Connect(IInterfaceFactory& factory) = 0;
202
204 virtual void Disconnect() = 0;
205
211 [[nodiscard]] virtual Result<void> Init() = 0;
212
214 virtual void Shutdown() = 0;
215
222 virtual IInterface* QueryInterface(std::string_view name, u32 version) {
223 (void)name;
224 (void)version;
225 return nullptr;
226 }
227};
228
236template <typename... Interfaces, typename Module>
237IInterface* FindModuleInterface(Module& module, std::string_view name, u32 version) {
238 IInterface* found = nullptr;
239 ((!found && name == Interfaces::kInterface.name && version == Interfaces::kInterface.version
240 ? (found = static_cast<Interfaces*>(&module))
241 : nullptr),
242 ...);
243 return found;
244}
245
246namespace detail {
247
252REX_API IInterfaceFactory* GetAppInterfaceFactory();
253
254} // namespace detail
255
258 public:
265 template <typename T>
266 static T* Get() {
267 IInterfaceFactory* factory = detail::GetAppInterfaceFactory();
268 return factory ? factory->Get<T>() : nullptr;
269 }
270};
271
272#define REX_INTERFACE(T) ::rex::AppInterfaces::Get<T>()
273
275inline constexpr const char* kCreateInterfaceSymbol = "ReXCreateInterface";
276
278inline constexpr const char* kEnumerateInterfacesSymbol = "ReXEnumerateInterfaces";
279
285inline constexpr const char* kBuildIdentitySymbol = "ReXBuildIdentity";
286
288using CreateInterfaceFn = IInterface* (*)(const char* name, u32 version);
289
291using EnumerateInterfacesFn = u32 (*)(InterfaceType* out, u32 capacity);
292
293namespace detail {
294
301template <typename... Interfaces>
302struct ServedTypeList {
303 static constexpr InterfaceType kList[] = {Interfaces::kInterface...};
304};
305
307inline std::vector<InterfaceType> ListServedInterfaces(const IModule& module) {
308 std::vector<InterfaceType> types{IModule::kInterface};
309 for (const InterfaceType& type : module.GetServedInterfaces()) {
310 if (std::string_view(type.name) != IModule::kInterface.name) {
311 types.push_back(type);
312 }
313 }
314 return types;
315}
316
317template <typename Module>
318IInterface* CreateModuleInterface(Module& module, std::string_view name, u32 version) {
319 if (name == IModule::kInterface.name && version == IModule::kInterface.version) {
320 return static_cast<IModule*>(&module);
321 }
322 return module.QueryInterface(name, version);
323}
324
325inline u32 EnumerateModuleInterfaces(const IModule& module, InterfaceType* out, u32 capacity) {
326 const std::vector<InterfaceType> types = ListServedInterfaces(module);
327 const u32 count = static_cast<u32>(types.size());
328 for (u32 i = 0; i < count && i < capacity; ++i) {
329 out[i] = types[i];
330 }
331 return count;
332}
333
334} // namespace detail
335} // namespace rex
336
351#define REX_MODULE_SERVES(...) \
352 ::std::span<const ::rex::InterfaceType> GetServedInterfaces() const override { \
353 return ::rex::detail::ServedTypeList<__VA_ARGS__>::kList; \
354 }
355
366#define REX_DECLARE_MODULE(ModuleClass) \
367 namespace { \
368 using ReXModuleType = ModuleClass; \
369 ReXModuleType& ReXModuleInstance() { \
370 static ModuleClass instance; \
371 return instance; \
372 } \
373 } \
374 extern "C" REX_DETAIL_EXPORT const char* ReXBuildIdentity() { \
375 return REXGLUE_BUILD_IDENTITY; \
376 } \
377 extern "C" REX_DETAIL_EXPORT ::rex::IInterface* ReXCreateInterface(const char* name, \
378 ::rex::u32 version) { \
379 return ::rex::detail::CreateModuleInterface<ModuleClass>(ReXModuleInstance(), name, version); \
380 } \
381 extern "C" REX_DETAIL_EXPORT ::rex::u32 ReXEnumerateInterfaces(::rex::InterfaceType* out, \
382 ::rex::u32 capacity) { \
383 return ::rex::detail::EnumerateModuleInterfaces(ReXModuleInstance(), out, capacity); \
384 }
Definition module.h:257
static T * Get()
Definition module.h:266
Definition module.h:131
std::vector< T * > FindAll()
Definition module.h:167
virtual IInterface * Find(std::string_view name, u32 version)=0
virtual std::vector< IInterface * > FindAll(std::string_view name, u32 version)=0
T * Get()
Definition module.h:156
Definition module.h:86
Definition module.h:177
#define REX_DECLARE_INTERFACE(Name, version)
Definition module.h:114
Definition app.h:36
constexpr const char * kEnumerateInterfacesSymbol
Definition module.h:278
constexpr const char * kCreateInterfaceSymbol
Definition module.h:275
IInterface * FindModuleInterface(Module &module, std::string_view name, u32 version)
Definition module.h:237
void Shutdown()
IInterface *(*)(const char *name, u32 version) CreateInterfaceFn
Definition module.h:288
std::expected< T, Error > Result
Definition result.h:98
u32(*)(InterfaceType *out, u32 capacity) EnumerateInterfacesFn
Definition module.h:291
Result< void > Init(const Config &config)
constexpr const char * kBuildIdentitySymbol
Definition module.h:285
Platform flags, packing macros and export markers.
#define REX_API
Definition platform.h:177
Definition module.h:79
const char * name
Definition module.h:80
bool is_private
Definition module.h:82
Integer types, byte order wrappers and size literals.
Move only function, const propagating pointer and scope guard.