1#include "ExtensionRegistry.h"
4#include "Foundation/Logging/Logger.h"
5#include "Foundation/Platform/Module.h"
16 GETEXTFN getExtension =
nullptr;
18 virtual void initPtrs()
override {
19 getProcAddress(getExtension,
"getExtension");
25 std::vector<Cogs::Module> extensionHandles;
29std::vector<Cogs::Core::Context *> Cogs::Core::ExtensionRegistry::contexts;
31bool Cogs::Core::ExtensionRegistry::initialized =
false;
32bool Cogs::Core::ExtensionRegistry::locked =
false;
36 LOG_INFO(logger,
"ExtensionRegistry::add Extension: %s", extension->getExtensionKey());
38 if (version.
empty()) {
39 LOG_WARNING(logger,
"Extension %s has no versioning info. Update registration method.", extension->getExtensionKey());
41 else if (version != internalVersion) {
42 LOG_WARNING(logger,
"Extension %s built against a different version (%s) than the current (%s).",
43 extension->getExtensionKey(),
45 internalVersion.data());
49 getDelayedExtensions().push_back(extension);
55 extension->initializeStatic();
57 for (
auto c : contexts) {
58 extension->initialize(c);
66 assert(key &&
"Extension search key cannot be nullptr.");
68 for (
auto extension : getExtensions()) {
69 if (key == extension->getExtensionKey()) {
75 LOG_WARNING(logger,
"No extension named %.*s found.", StringViewFormat(key));
83 for (
auto e : getExtensions()) {
84 if (strcmp(extension, e->getExtensionKey()) == 0) {
85 return e->getSymbolPointer(name);
94 const char* key = extension->getExtensionKey();
97 LOG_INFO(logger,
"Initialized static extension: %s.", key);
100 extension->initializeStatic();
108 for (
auto extension : getExtensions()) {
109 extension->initialize(context);
112 contexts.push_back(context);
117 for (
auto & e : getExtensions()) {
124 contexts.erase(std::remove(std::begin(contexts), std::end(contexts), context), std::end(contexts));
129 const auto count = getExtensions().size();
134 auto module = Module::load<ExtensionModule>(path);
137 if (module.status == Module::LoadStatus::Failed) {
138 LOG_ERROR(logger,
"Failed loading extension module %s.", path.c_str());
141 *result = ExtensionModuleLoadResult::Failure;
150 std::deque<Extension*>& delayedExtensions = getDelayedExtensions();
152 while (!delayedExtensions.empty()) {
153 Extension* e = delayedExtensions.front();
155 delayedExtensions.pop_front();
158 LOG_ERROR(logger,
"Extension %s failed static initialisation.", path.c_str());
161 *result = ExtensionModuleLoadResult::Failure;
163 Module::unload(module.handle);
166 for (
auto context : contexts) {
168 LOG_ERROR(logger,
"Extension %s failed to initialise.", path.c_str());
171 *result = ExtensionModuleLoadResult::Failure;
173 Module::unload(module.handle);
177 getExtensions().push_back(e);
181 *modulehandle = module.handle;
184 if (std::find(std::begin(extensionHandles), std::end(extensionHandles), module) != std::end(extensionHandles)) {
187 else if (getExtensions().size() <= count) {
188 if (path !=
"Cogs.Core.Extensions.Terrain") {
190 LOG_WARNING(logger,
"No extensions were found in module %s.", path.c_str());
194 *result = ExtensionModuleLoadResult::NoExtensionsFound;
199 LOG_INFO(logger,
"Extension %s loaded successfully.", path.c_str());
200 extensionHandles.push_back(module);
203 return module.getExtension ? module.getExtension()->getPublicAPI() :
reinterpret_cast<const void*
>(-1);
208 static std::vector<Extension *> extensions;
213std::deque<Cogs::Core::Extension*>& Cogs::Core::ExtensionRegistry::getDelayedExtensions()
215 static std::deque<Extension*> delayedExtenions;
217 return delayedExtenions;
A Context instance contains all the services, systems and runtime components needed to use Cogs.
static void add(Extension *extension, StringView version)
Adds the given extension to the registry, ensuring the initialization methods are called at appropria...
static void cleanup(Context *context)
Cleanup the given context.
static bool hasExtension(const StringView &key, bool silent=false)
Check if an extension with the given key is present in this build.
static void remove(Context *context)
Removes the given context.
static void initialize(Context *context)
Performs initialization of all extensions registered with add().
static void initializeStatic()
Performs static initialization of all extensions registered with add().
static std::vector< Extension * > & getExtensions()
Get the extension registry.
static const void * loadExtensionModule(const std::string &path, void **modulehandle=nullptr, ExtensionModuleLoadResult *result=nullptr)
Load the extension module with the given name.
ExtensionModuleLoadResult
Defines possible results of an extension module load.
static void * getExtensionSymbol(const char *extension, const char *name)
Retrieves the address of a symbol in the extension module.
Log implementation class.
Base class for managing libraries dynamically loaded at runtime.
Provides a weakly referenced view over the contents of a string.
constexpr const char * data() const noexcept
Get the sequence of characters referenced by the string view.
constexpr bool empty() const noexcept
Check if the string is empty.
constexpr Log getLogger(const char(&name)[LEN]) noexcept
Defines an extension to Cogs.Core and provides methods to override in order to initialize extension c...
virtual bool initialize(Context *)
Initialize extension for the given context.
virtual bool initializeStatic()
Initialize extension statically.