-
Notifications
You must be signed in to change notification settings - Fork 17
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
Showing
8 changed files
with
347 additions
and
1 deletion.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,19 @@ | ||
#pragma once | ||
|
||
namespace engine | ||
{ | ||
|
||
// After loading a dll, we need to call an Init function to create inherited IModule object. | ||
// So there is a rule about this Init function's name and ABI declaration. | ||
static constexpr const char* ModuleInitFunctioName = "InitializeModule"; | ||
using ModuleInitFunctionPtr = void* (*)(void); | ||
|
||
class IModule | ||
{ | ||
public: | ||
virtual ~IModule() {} | ||
|
||
void Shutdown(); | ||
}; | ||
|
||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,68 @@ | ||
#include "Module.h" | ||
|
||
#include "Core/OS/DllUtils.h" | ||
#include "Path/Path.h" | ||
|
||
#include <cassert> | ||
|
||
namespace engine | ||
{ | ||
|
||
ModuleLoadResult Module::Load() | ||
{ | ||
if (IsLoaded()) | ||
{ | ||
assert(m_handle && m_module); | ||
return ModuleLoadResult::AlreadyLoaded; | ||
} | ||
|
||
bool dllFileExists = Path::FileExists(m_filePath.c_str()); | ||
if (!dllFileExists) | ||
{ | ||
return ModuleLoadResult::FileNotExist; | ||
} | ||
|
||
m_handle = DllUtils::LoadDll(m_filePath.c_str()); | ||
if (!m_handle) | ||
{ | ||
return ModuleLoadResult::LoadDllFailure; | ||
} | ||
|
||
auto initFunc = reinterpret_cast<ModuleInitFunctionPtr>(DllUtils::LoadDllFunction(m_handle, ModuleInitFunctioName)); | ||
if (!initFunc) | ||
{ | ||
Unload(); | ||
return ModuleLoadResult::InterfaceMissing; | ||
} | ||
|
||
void* pModule = initFunc(); | ||
if (!pModule) | ||
{ | ||
Unload(); | ||
return ModuleLoadResult::InitFailure; | ||
} | ||
|
||
m_module.reset(reinterpret_cast<engine::IModule*>(pModule)); | ||
m_status = ModuleStatus::Loaded; | ||
|
||
return ModuleLoadResult::Success; | ||
} | ||
|
||
void Module::Unload() | ||
{ | ||
if (m_module) | ||
{ | ||
m_module->Shutdown(); | ||
m_module.reset(nullptr); | ||
} | ||
|
||
if (m_handle) | ||
{ | ||
DllUtils::UnloadDll(m_handle); | ||
m_handle = nullptr; | ||
} | ||
|
||
m_status = ModuleStatus::Unload; | ||
} | ||
|
||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,82 @@ | ||
#pragma once | ||
|
||
#include "Base/Template.h" | ||
#include "IModule.h" | ||
#include "IO/InputArchive.hpp" | ||
#include "IO/OutputArchive.hpp" | ||
|
||
#include <memory> | ||
#include <string> | ||
|
||
namespace engine | ||
{ | ||
|
||
enum class ModuleStatus | ||
{ | ||
Unload, | ||
Loaded, | ||
}; | ||
|
||
enum class ModuleLoadResult | ||
{ | ||
AlreadyLoaded, | ||
FileNotExist, | ||
LoadDllFailure, | ||
InterfaceMissing, | ||
InitFailure, | ||
Success | ||
}; | ||
|
||
class Module | ||
{ | ||
public: | ||
Module() = default; | ||
Module(const Module&) = delete; | ||
Module& operator=(const Module&) = delete; | ||
Module(Module&&) = default; | ||
Module& operator=(Module&&) = default; | ||
~Module() = default; | ||
|
||
void SetName(std::string name) { m_name = cd::MoveTemp(name); } | ||
std::string& GetName() { return m_name; } | ||
const std::string& GetName() const { return m_name; } | ||
|
||
void SetFilePath(std::string path) { m_filePath = cd::MoveTemp(path); } | ||
std::string& GetFilePath() { return m_filePath; } | ||
const std::string& GetFilePath() const { return m_filePath; } | ||
|
||
void SetAutoLoad(bool on) { m_autoLoad = on; } | ||
bool& GetAutoLoad() { return m_autoLoad; } | ||
bool GetAutoLoad() const { return m_autoLoad; } | ||
|
||
bool IsLoaded() const { return ModuleStatus::Loaded == m_status; } | ||
ModuleLoadResult Load(); | ||
void Unload(); | ||
|
||
template<bool SwapBytesOrder> | ||
Module& operator<<(cd::TInputArchive<SwapBytesOrder>& inputArchive) | ||
{ | ||
inputArchive >> GetName() >> GetFilePath() >> GetAutoLoad(); | ||
return *this; | ||
} | ||
|
||
template<bool SwapBytesOrder> | ||
const Module& operator>>(cd::TOutputArchive<SwapBytesOrder>& outputArchive) const | ||
{ | ||
outputArchive << GetName() << GetFilePath() << GetAutoLoad(); | ||
return *this; | ||
} | ||
|
||
private: | ||
// Configs | ||
std::string m_name; | ||
std::string m_filePath; | ||
bool m_autoLoad = false; | ||
|
||
// Runtime | ||
ModuleStatus m_status = ModuleStatus::Unload; | ||
void* m_handle = nullptr; | ||
std::unique_ptr<IModule> m_module; | ||
}; | ||
|
||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,73 @@ | ||
#include "ModuleManager.h" | ||
|
||
#include "Module.h" | ||
#include "Path/Path.h" | ||
|
||
namespace engine | ||
{ | ||
|
||
ModuleManager::~ModuleManager() = default; | ||
|
||
void ModuleManager::LoadModules(bool checkAutoLoad) | ||
{ | ||
for (auto& [_, module] : m_allModules) | ||
{ | ||
if (!module->IsLoaded()) | ||
{ | ||
if (checkAutoLoad && module->GetAutoLoad()) | ||
{ | ||
module->Load(); | ||
} | ||
} | ||
} | ||
} | ||
|
||
void ModuleManager::UnloadModules() | ||
{ | ||
for (auto& [_, module] : m_allModules) | ||
{ | ||
if (module->IsLoaded()) | ||
{ | ||
module->Unload(); | ||
} | ||
} | ||
} | ||
|
||
Module* ModuleManager::AddModule(const char* pFilePath) | ||
{ | ||
std::string moduleName = Path::GetFileNameWithoutExtension(pFilePath); | ||
StringCrc moduleCrc(moduleName); | ||
if (auto* pModule = GetModule(moduleCrc)) | ||
{ | ||
return pModule; | ||
} | ||
|
||
auto module = std::make_unique<Module>(); | ||
Module* pModule = module.get(); | ||
m_allModules[moduleCrc] = cd::MoveTemp(module); | ||
|
||
pModule->SetName(cd::MoveTemp(moduleName)); | ||
pModule->SetFilePath(pFilePath); | ||
return pModule; | ||
} | ||
|
||
bool ModuleManager::FindModule(StringCrc moduleCrc) const | ||
{ | ||
return m_allModules.find(moduleCrc) != m_allModules.end(); | ||
} | ||
|
||
Module* ModuleManager::GetModule(StringCrc moduleCrc) const | ||
{ | ||
auto itModule = m_allModules.find(moduleCrc); | ||
return itModule != m_allModules.end() ? itModule->second.get() : nullptr; | ||
} | ||
|
||
void ModuleManager::RemoveModule(StringCrc moduleCrc) | ||
{ | ||
if (auto itModule = m_allModules.find(moduleCrc); itModule != m_allModules.end()) | ||
{ | ||
m_allModules.erase(itModule); | ||
} | ||
} | ||
|
||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,65 @@ | ||
#pragma once | ||
|
||
#include "Core/StringCrc.h" | ||
#include "IO/InputArchive.hpp" | ||
#include "IO/OutputArchive.hpp" | ||
|
||
#include <map> | ||
#include <memory> | ||
#include <string> | ||
|
||
namespace engine | ||
{ | ||
|
||
class Module; | ||
|
||
class ModuleManager | ||
{ | ||
public: | ||
ModuleManager() = default; | ||
ModuleManager(const ModuleManager&) = delete; | ||
ModuleManager& operator=(const ModuleManager&) = delete; | ||
ModuleManager(ModuleManager&&) = default; | ||
ModuleManager& operator=(ModuleManager&&) = default; | ||
~ModuleManager(); | ||
|
||
void LoadModules(bool checkAutoLoad = true); | ||
void UnloadModules(); | ||
|
||
Module* AddModule(const char* pFilePath); | ||
bool FindModule(StringCrc moduleCrc) const; | ||
Module* GetModule(StringCrc moduleCrc) const; | ||
void RemoveModule(StringCrc moduleCrc); | ||
|
||
template<bool SwapBytesOrder> | ||
ModuleManager& operator<<(cd::TInputArchive<SwapBytesOrder>& inputArchive) | ||
{ | ||
uint32_t moduleCount; | ||
inputArchive >> moduleCount; | ||
for (uint32_t moduleIndex = 0U; moduleIndex < moduleCount; ++moduleIndex) | ||
{ | ||
Module module; | ||
inputArchive >> module; | ||
AddModule(module.GetFilePath().c_str()); | ||
} | ||
|
||
return *this; | ||
} | ||
|
||
template<bool SwapBytesOrder> | ||
const ModuleManager& operator>>(cd::TOutputArchive<SwapBytesOrder>& outputArchive) const | ||
{ | ||
outputArchive << static_cast<uint32_t>(m_allModules.size()); | ||
for (const auto& module : m_allModules) | ||
{ | ||
outputArchive << module; | ||
} | ||
|
||
return *this; | ||
} | ||
|
||
private: | ||
std::map<StringCrc, std::unique_ptr<Module>> m_allModules; | ||
}; | ||
|
||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,23 @@ | ||
#include "DllUtils.h" | ||
|
||
#include "SDL.h" | ||
|
||
namespace engine | ||
{ | ||
|
||
void* DllUtils::LoadDll(const char* pFilePath) | ||
{ | ||
return SDL_LoadObject(pFilePath); | ||
} | ||
|
||
void* DllUtils::LoadDllFunction(void* pHandle, const char* pFunctionName) | ||
{ | ||
return SDL_LoadFunction(pHandle, pFunctionName); | ||
} | ||
|
||
void DllUtils::UnloadDll(void* pHandle) | ||
{ | ||
return SDL_UnloadObject(pHandle); | ||
} | ||
|
||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,16 @@ | ||
#pragma once | ||
|
||
namespace engine | ||
{ | ||
|
||
class DllUtils | ||
{ | ||
public: | ||
DllUtils() = delete; | ||
|
||
static void* LoadDll(const char* pFilePath); | ||
static void* LoadDllFunction(void* pHandle, const char* pFunctionName); | ||
static void UnloadDll(void* pHandle); | ||
}; | ||
|
||
} |