113 lines
3.1 KiB
C++
113 lines
3.1 KiB
C++
#ifndef MODULES_HPP
|
|
#define MODULES_HPP
|
|
|
|
#include <iostream>
|
|
#include <string>
|
|
#include <unordered_map>
|
|
|
|
#if defined(_WIN32) || defined(_WIN64)
|
|
#define PLATFORM_WINDOWS
|
|
#define WIN32_LEAN_AND_MEAN
|
|
#include <windows.h>
|
|
#elif defined(__linux__)
|
|
#define PLATFORM_LINUX
|
|
#include <dlfcn.h>
|
|
#else
|
|
#error "Unsupported platform (Windows and Linux only)."
|
|
#endif
|
|
|
|
using InitFunc = void(*)();
|
|
|
|
class ModuleManager {
|
|
public:
|
|
ModuleManager() = default;
|
|
|
|
~ModuleManager() {
|
|
UnloadAll();
|
|
}
|
|
|
|
ModuleManager(const ModuleManager&) = delete;
|
|
ModuleManager& operator=(const ModuleManager&) = delete;
|
|
|
|
bool LoadModule(const std::string& path, const std::string& initFuncName = "initialize") {
|
|
if (modules.find(path) != modules.end()) {
|
|
std::cerr << "[ModuleManager] Module is already loaded: " << path << std::endl;
|
|
return false;
|
|
}
|
|
|
|
#if defined(PLATFORM_WINDOWS)
|
|
HMODULE handle = LoadLibraryA(path.c_str());
|
|
if (!handle) {
|
|
std::cerr << "[ModuleManager] Failed to load DLL (" << path << "): Code " << GetLastError() << std::endl;
|
|
return false;
|
|
}
|
|
|
|
auto init = reinterpret_cast<InitFunc>(GetProcAddress(handle, initFuncName.c_str()));
|
|
if (!init) {
|
|
std::cerr << "[ModuleManager] Function '" << initFuncName << "' not found in: " << path << std::endl;
|
|
FreeLibrary(handle);
|
|
return false;
|
|
}
|
|
#elif defined(PLATFORM_LINUX)
|
|
void* handle = dlopen(path.c_str(), RTLD_NOW);
|
|
if (!handle) {
|
|
std::cerr << "[ModuleManager] Failed to load SO (" << path << "): " << dlerror() << std::endl;
|
|
return false;
|
|
}
|
|
|
|
dlerror();
|
|
|
|
auto init = reinterpret_cast<InitFunc>(dlsym(handle, initFuncName.c_str()));
|
|
const char* dlsym_error = dlerror();
|
|
if (dlsym_error) {
|
|
std::cerr << "[ModuleManager] Function '" << initFuncName << "' not found: " << dlsym_error << std::endl;
|
|
dlclose(handle);
|
|
return false;
|
|
}
|
|
#endif
|
|
|
|
init();
|
|
|
|
modules[path] = handle;
|
|
|
|
std::cout << "[ModuleManager] Module successfully loaded and initialized: " << path << std::endl;
|
|
return true;
|
|
}
|
|
|
|
bool UnloadModule(const std::string& path) {
|
|
auto it = modules.find(path);
|
|
if (it == modules.end()) {
|
|
return false;
|
|
}
|
|
|
|
#if defined(PLATFORM_WINDOWS)
|
|
FreeLibrary(static_cast<HMODULE>(it->second));
|
|
#elif defined(PLATFORM_LINUX)
|
|
dlclose(it->second);
|
|
#endif
|
|
|
|
modules.erase(it);
|
|
std::cout << "[ModuleManager] Module unloaded: " << path << std::endl;
|
|
return true;
|
|
}
|
|
|
|
void UnloadAll() {
|
|
for (auto& [path, handle] : modules) {
|
|
#if defined(PLATFORM_WINDOWS)
|
|
FreeLibrary(static_cast<HMODULE>(handle));
|
|
#elif defined(PLATFORM_LINUX)
|
|
dlclose(handle);
|
|
#endif
|
|
}
|
|
modules.clear();
|
|
}
|
|
|
|
private:
|
|
#if defined(PLATFORM_WINDOWS)
|
|
std::unordered_map<std::string, HMODULE> modules;
|
|
#elif defined(PLATFORM_LINUX)
|
|
std::unordered_map<std::string, void*> modules;
|
|
#endif
|
|
};
|
|
|
|
#endif |