#include #include #include ModuleManager::Module_t ModuleManager::loadModule(std::string path) { Module_t mod; // On android, the path has to be relative, don't make it absolute #ifndef __ANDROID__ if (!std::filesystem::exists(path)) { spdlog::error("{0} does not exist", path); mod.handle = NULL; return mod; } if (!std::filesystem::is_regular_file(path)) { spdlog::error("{0} isn't a loadable module", path); mod.handle = NULL; return mod; } #endif #ifdef _WIN32 mod.handle = LoadLibraryA(path.c_str()); if (mod.handle == NULL) { spdlog::error("Couldn't load {0}. Error code: {1}", path, GetLastError()); mod.handle = NULL; return mod; } mod.info = (ModuleInfo_t*)GetProcAddress(mod.handle, "_INFO_"); mod.init = (void (*)())GetProcAddress(mod.handle, "_INIT_"); mod.createInstance = (Instance * (*)(std::string)) GetProcAddress(mod.handle, "_CREATE_INSTANCE_"); mod.deleteInstance = (void (*)(Instance*))GetProcAddress(mod.handle, "_DELETE_INSTANCE_"); mod.end = (void (*)())GetProcAddress(mod.handle, "_END_"); #else mod.handle = dlopen(path.c_str(), RTLD_LAZY | RTLD_LOCAL); if (mod.handle == NULL) { spdlog::error("Couldn't load {0}.", path); mod.handle = NULL; return mod; } mod.info = (ModuleInfo_t*)dlsym(mod.handle, "_INFO_"); mod.init = (void (*)())dlsym(mod.handle, "_INIT_"); mod.createInstance = (Instance * (*)(std::string)) dlsym(mod.handle, "_CREATE_INSTANCE_"); mod.deleteInstance = (void (*)(Instance*))dlsym(mod.handle, "_DELETE_INSTANCE_"); mod.end = (void (*)())dlsym(mod.handle, "_END_"); #endif if (mod.info == NULL) { spdlog::error("{0} is missing _INFO_ symbol", path); mod.handle = NULL; return mod; } if (mod.init == NULL) { spdlog::error("{0} is missing _INIT_ symbol", path); mod.handle = NULL; return mod; } if (mod.createInstance == NULL) { spdlog::error("{0} is missing _CREATE_INSTANCE_ symbol", path); mod.handle = NULL; return mod; } if (mod.deleteInstance == NULL) { spdlog::error("{0} is missing _DELETE_INSTANCE_ symbol", path); mod.handle = NULL; return mod; } if (mod.end == NULL) { spdlog::error("{0} is missing _END_ symbol", path); mod.handle = NULL; return mod; } if (modules.find(mod.info->name) != modules.end()) { spdlog::error("{0} has the same name as an already loaded module", path); mod.handle = NULL; return mod; } for (auto const& [name, _mod] : modules) { if (mod.handle == _mod.handle) { return _mod; } } mod.init(); modules[mod.info->name] = mod; return mod; } int ModuleManager::createInstance(std::string name, std::string module) { if (modules.find(module) == modules.end()) { spdlog::error("Module '{0}' doesn't exist", module); return -1; } if (instances.find(name) != instances.end()) { spdlog::error("A module instance with the name '{0}' already exists", name); return -1; } int maxCount = modules[module].info->maxInstances; if (countModuleInstances(module) >= maxCount && maxCount > 0) { spdlog::error("Maximum number of instances reached for '{0}'", module); return -1; } Instance_t inst; inst.module = modules[module]; inst.instance = inst.module.createInstance(name); instances[name] = inst; onInstanceCreated.emit(name); return 0; } int ModuleManager::deleteInstance(std::string name) { if (instances.find(name) == instances.end()) { spdlog::error("Tried to remove non-existent instance '{0}'", name); return -1; } onInstanceDelete.emit(name); Instance_t inst = instances[name]; inst.module.deleteInstance(inst.instance); instances.erase(name); onInstanceDeleted.emit(name); return 0; } int ModuleManager::deleteInstance(ModuleManager::Instance* instance) { spdlog::error("Delete instance not implemented"); return -1; } int ModuleManager::enableInstance(std::string name) { if (instances.find(name) == instances.end()) { spdlog::error("Cannot enable '{0}', instance doesn't exist", name); return -1; } instances[name].instance->enable(); return 0; } int ModuleManager::disableInstance(std::string name) { if (instances.find(name) == instances.end()) { spdlog::error("Cannot disable '{0}', instance doesn't exist", name); return -1; } instances[name].instance->disable(); return 0; } bool ModuleManager::instanceEnabled(std::string name) { if (instances.find(name) == instances.end()) { spdlog::error("Cannot check if '{0}' is enabled, instance doesn't exist", name); return false; } return instances[name].instance->isEnabled(); } void ModuleManager::postInit(std::string name) { if (instances.find(name) == instances.end()) { spdlog::error("Cannot post-init '{0}', instance doesn't exist", name); return; } instances[name].instance->postInit(); } std::string ModuleManager::getInstanceModuleName(std::string name) { if (instances.find(name) == instances.end()) { spdlog::error("Cannot get module name of'{0}', instance doesn't exist", name); return ""; } return std::string(instances[name].module.info->name); } int ModuleManager::countModuleInstances(std::string module) { if (modules.find(module) == modules.end()) { spdlog::error("Cannot count instances of '{0}', Module doesn't exist", module); return -1; } ModuleManager::Module_t mod = modules[module]; int count = 0; for (auto const& [name, instance] : instances) { if (instance.module == mod) { count++; } } return count; } void ModuleManager::doPostInitAll() { for (auto& [name, inst] : instances) { spdlog::info("Running post-init for {0}", name); inst.instance->postInit(); } }