From 932f6857459acca80ace52a9160defc2f0567fd1 Mon Sep 17 00:00:00 2001 From: Yann Date: Fri, 22 Mar 2024 16:34:13 +0100 Subject: [PATCH 1/4] feat(DLLoader): implement DLLoader component --- common/games/IGameProvider.hpp | 2 +- common/games/export.cpp.example | 4 +- common/graphics/IGraphicsProvider.hpp | 2 +- common/graphics/export.cpp.example | 2 +- common/types/Libraries.hpp | 3 +- core/CMakeLists.txt | 5 ++ core/main.cpp | 10 ++++ core/src/CMakeLists.txt | 2 + core/src/exception/ArcadeError.cpp | 14 +++++ core/src/exception/ArcadeError.hpp | 19 +++++++ core/src/exception/CMakeLists.txt | 3 ++ core/src/loader/CMakeLists.txt | 3 ++ core/src/loader/DLLoader.cpp | 75 +++++++++++++++++++++++++++ core/src/loader/DLLoader.hpp | 44 ++++++++++++++++ core/src/types/Providers.hpp | 13 +++++ 15 files changed, 195 insertions(+), 6 deletions(-) create mode 100644 core/src/CMakeLists.txt create mode 100644 core/src/exception/ArcadeError.cpp create mode 100644 core/src/exception/ArcadeError.hpp create mode 100644 core/src/exception/CMakeLists.txt create mode 100644 core/src/loader/CMakeLists.txt create mode 100644 core/src/loader/DLLoader.cpp create mode 100644 core/src/loader/DLLoader.hpp create mode 100644 core/src/types/Providers.hpp diff --git a/common/games/IGameProvider.hpp b/common/games/IGameProvider.hpp index bd4b07d..ddb2bcd 100644 --- a/common/games/IGameProvider.hpp +++ b/common/games/IGameProvider.hpp @@ -32,5 +32,5 @@ class shared::games::IGameProvider * * @return Created game instance */ - virtual std::shared_ptr createInstance(void) = 0; + virtual std::shared_ptr createInstance(void) = 0; }; diff --git a/common/games/export.cpp.example b/common/games/export.cpp.example index 4fe9f03..12b4ae3 100644 --- a/common/games/export.cpp.example +++ b/common/games/export.cpp.example @@ -6,7 +6,7 @@ */ #include "IGame.hpp" -#include "../types/LibraryType.hpp" +#include "../types/Libraries.hpp" extern "C" { shared::types::LibraryType SHARED_LIBRARY_TYPE_GETTER_NAME(void) @@ -14,7 +14,7 @@ extern "C" { return shared::types::LibraryType::GAME; } - std::shared_ptr SHARED_GRAPHICS_FACTORY_LOADER_NAME(void) + std::shared_ptr SHARED_GAME_PROVIDER_LOADER_NAME(void) { return std::make_shared(...) } diff --git a/common/graphics/IGraphicsProvider.hpp b/common/graphics/IGraphicsProvider.hpp index 16dc666..eab2ca9 100644 --- a/common/graphics/IGraphicsProvider.hpp +++ b/common/graphics/IGraphicsProvider.hpp @@ -28,7 +28,7 @@ class shared::graphics::IGraphicsProvider { * * @return Manifest of the graphics library */ - virtual const GameManifest &getManifest(void) const noexcept = 0; + virtual const GraphicsManifest &getManifest(void) const noexcept = 0; /** * @brief Create a renderer object diff --git a/common/graphics/export.cpp.example b/common/graphics/export.cpp.example index ae4ef20..d3e00de 100644 --- a/common/graphics/export.cpp.example +++ b/common/graphics/export.cpp.example @@ -14,7 +14,7 @@ extern "C" { return shared::types::LibraryType::GRAPHIC; } - std::shared_ptr SHARED_GAME_PROVIDER_LOADER_NAME(void) + std::shared_ptr SHARED_GRAPHICS_PROVIDER_LOADER_NAME(void) { return std::make_shared(...); } diff --git a/common/types/Libraries.hpp b/common/types/Libraries.hpp index 08c954b..999c223 100644 --- a/common/types/Libraries.hpp +++ b/common/types/Libraries.hpp @@ -13,7 +13,8 @@ #define SHARED_GAME_PROVIDER_LOADER_NAME arcadeLibGetGameProvider #define SHARED_GRAPHICS_PROVIDER_LOADER_NAME arcadeLibGetGraphicsProvider #define SHARED_LIBRARY_TYPE_GETTER_NAME arcadeLibGetType -#define SHARED_STRINGIFY(x) #x +#define STRINGIFY(x) #x +#define SHARED_STRINGIFY(x) STRINGIFY(x) namespace shared::types { diff --git a/core/CMakeLists.txt b/core/CMakeLists.txt index 47a7d54..95198b9 100644 --- a/core/CMakeLists.txt +++ b/core/CMakeLists.txt @@ -1,3 +1,8 @@ add_executable(arcade main.cpp ) + +target_include_directories(arcade PUBLIC ${CMAKE_CURRENT_LIST_DIR}/..) +target_include_directories(arcade PUBLIC ${CMAKE_CURRENT_LIST_DIR}/src) + +add_subdirectory(src) diff --git a/core/main.cpp b/core/main.cpp index 904ff7a..8a72f78 100644 --- a/core/main.cpp +++ b/core/main.cpp @@ -5,7 +5,17 @@ ** main */ +#include "loader/DLLoader.hpp" + int main(void) { + DLLoader loader; + + try { + loader.loadLibraries("./lib"); + std::cout << "Games libraries:" << loader.getGamesLibraries().size() << std::endl; + } catch (const std::exception &e) { + std::cerr << e.what() << std::endl; + } return 0; } diff --git a/core/src/CMakeLists.txt b/core/src/CMakeLists.txt new file mode 100644 index 0000000..b3a80a9 --- /dev/null +++ b/core/src/CMakeLists.txt @@ -0,0 +1,2 @@ +add_subdirectory(exception) +add_subdirectory(loader) \ No newline at end of file diff --git a/core/src/exception/ArcadeError.cpp b/core/src/exception/ArcadeError.cpp new file mode 100644 index 0000000..c96faaa --- /dev/null +++ b/core/src/exception/ArcadeError.cpp @@ -0,0 +1,14 @@ +/* +** EPITECH PROJECT, 2024 +** arcade +** File description: +** ArcadeError +*/ + +#include "ArcadeError.hpp" + +ArcadeError::ArcadeError(std::string const &message) : _message(message) {} + +const char *ArcadeError::what() const noexcept { + return this->_message.c_str(); +} diff --git a/core/src/exception/ArcadeError.hpp b/core/src/exception/ArcadeError.hpp new file mode 100644 index 0000000..e4bee8a --- /dev/null +++ b/core/src/exception/ArcadeError.hpp @@ -0,0 +1,19 @@ +/* +** EPITECH PROJECT, 2024 +** arcade +** File description: +** ArcadeError +*/ + +#pragma once + +#include + +class ArcadeError : public std::exception { + public: + explicit ArcadeError(std::string const &message); + + const char *what() const noexcept; + private: + const std::string _message; +}; diff --git a/core/src/exception/CMakeLists.txt b/core/src/exception/CMakeLists.txt new file mode 100644 index 0000000..a591306 --- /dev/null +++ b/core/src/exception/CMakeLists.txt @@ -0,0 +1,3 @@ +target_sources(arcade PRIVATE + ArcadeError.cpp +) diff --git a/core/src/loader/CMakeLists.txt b/core/src/loader/CMakeLists.txt new file mode 100644 index 0000000..92e7266 --- /dev/null +++ b/core/src/loader/CMakeLists.txt @@ -0,0 +1,3 @@ +target_sources(arcade PRIVATE + DLLoader.cpp +) \ No newline at end of file diff --git a/core/src/loader/DLLoader.cpp b/core/src/loader/DLLoader.cpp new file mode 100644 index 0000000..048b898 --- /dev/null +++ b/core/src/loader/DLLoader.cpp @@ -0,0 +1,75 @@ +/* +** EPITECH PROJECT, 2024 +** arcade +** File description: +** DLLoader +*/ + +#include +#include +#include +#include +#include "DLLoader.hpp" +#include "exception/ArcadeError.hpp" + +void DLLoader::registerLibrary(const std::string &path) { + void *handle = dlopen(path.c_str(), RTLD_LAZY); + shared::types::LibraryTypeGetter getter; + shared::types::LibraryType type; + shared::types::GameProvider game; + shared::types::GraphicsProvider graphics; + + std::cout << path << std::endl; + if (!handle) + throw ArcadeError("Cannot load library: " + path); + getter = reinterpret_cast(dlsym(handle, SHARED_STRINGIFY(SHARED_LIBRARY_TYPE_GETTER_NAME))); + if (!getter) { + dlclose(handle); + throw ArcadeError("Cannot find getter in library: " + path); + } + type = getter(); + if (type == shared::types::LibraryType::GAME) { + game = reinterpret_cast(dlsym(handle, SHARED_STRINGIFY(SHARED_GAME_PROVIDER_LOADER_NAME))); + if (!game) { + dlclose(handle); + throw ArcadeError("Cannot find game provider in library: " + path); + } + this->_gamesLibraries.push_back(game()); + } + if (type == shared::types::LibraryType::GRAPHIC) { + graphics = reinterpret_cast(dlsym(handle, SHARED_STRINGIFY(SHARED_GRAPHICS_PROVIDER_LOADER_NAME))); + if (!graphics) { + dlclose(handle); + throw ArcadeError("Cannot find graphics provider in library: " + path); + } + this->_graphicsLibraries.push_back(graphics()); + } +} + +void DLLoader::loadLibraries(std::string path) { + DIR *dir; + struct dirent *ent; + + std::cout << path << std::endl; + dir = opendir(path.c_str()); + if (!dir) + return; + ent = readdir(dir); + while (ent) { + if (ent->d_name[0] == '.') { + ent = readdir(dir); + continue; + } + this->registerLibrary(path + "/" + ent->d_name); + ent = readdir(dir); + } + closedir(dir); +} + +LoaderGamesProvider DLLoader::getGamesLibraries() const { + return this->_gamesLibraries; +} + +LoaderGraphicsProvider DLLoader::getGraphicsLibraries() const { + return this->_graphicsLibraries; +} diff --git a/core/src/loader/DLLoader.hpp b/core/src/loader/DLLoader.hpp new file mode 100644 index 0000000..fd08420 --- /dev/null +++ b/core/src/loader/DLLoader.hpp @@ -0,0 +1,44 @@ +/* +** EPITECH PROJECT, 2024 +** arcade +** File description: +** DLLoader +*/ + +#pragma once + +#include +#include "types/Providers.hpp" + +class DLLoader { + public: + + /** + * @brief Register a library + * @param path std::string + */ + void registerLibrary(const std::string &path); + + /** + * @brief Load all libraries in the given folder path + * @param path std::string + */ + void loadLibraries(std::string path); + + /** + * @brief Get all games libraries + * @return Loaded games libraries + */ + LoaderGamesProvider getGamesLibraries() const; + + /** + * @brief Get all graphics libraries + * @return Loaded graphics libraries + */ + LoaderGraphicsProvider getGraphicsLibraries() const; + + private: + const std::string _path; + LoaderGamesProvider _gamesLibraries; + LoaderGraphicsProvider _graphicsLibraries; +}; diff --git a/core/src/types/Providers.hpp b/core/src/types/Providers.hpp new file mode 100644 index 0000000..e157e32 --- /dev/null +++ b/core/src/types/Providers.hpp @@ -0,0 +1,13 @@ +/* +** EPITECH PROJECT, 2024 +** arcade +** File description: +** Providers +*/ + +#pragma once + +#include "common/types/Libraries.hpp" + +typedef std::vector> LoaderGamesProvider; +typedef std::vector> LoaderGraphicsProvider; From c0f5abad275d711ea3529bd385c581d586b0033f Mon Sep 17 00:00:00 2001 From: Yann Date: Fri, 22 Mar 2024 16:35:15 +0100 Subject: [PATCH 2/4] feat(DLLoader): throw an error when cannot open folder --- core/main.cpp | 1 + core/src/loader/DLLoader.cpp | 2 +- 2 files changed, 2 insertions(+), 1 deletion(-) diff --git a/core/main.cpp b/core/main.cpp index 8a72f78..6e160ea 100644 --- a/core/main.cpp +++ b/core/main.cpp @@ -14,6 +14,7 @@ int main(void) try { loader.loadLibraries("./lib"); std::cout << "Games libraries:" << loader.getGamesLibraries().size() << std::endl; + std::cout << "Graphics libraries:" << loader.getGraphicsLibraries().size() << std::endl; } catch (const std::exception &e) { std::cerr << e.what() << std::endl; } diff --git a/core/src/loader/DLLoader.cpp b/core/src/loader/DLLoader.cpp index 048b898..e9335fc 100644 --- a/core/src/loader/DLLoader.cpp +++ b/core/src/loader/DLLoader.cpp @@ -53,7 +53,7 @@ void DLLoader::loadLibraries(std::string path) { std::cout << path << std::endl; dir = opendir(path.c_str()); if (!dir) - return; + throw ArcadeError("Cannot open directory: " + path); ent = readdir(dir); while (ent) { if (ent->d_name[0] == '.') { From 3582ba2a1b146ebc8201fa50eb48824c30c021f0 Mon Sep 17 00:00:00 2001 From: Yann Date: Fri, 22 Mar 2024 16:38:57 +0100 Subject: [PATCH 3/4] fix: add very usefull breaklines --- core/src/CMakeLists.txt | 2 +- core/src/loader/CMakeLists.txt | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/core/src/CMakeLists.txt b/core/src/CMakeLists.txt index b3a80a9..a72ba11 100644 --- a/core/src/CMakeLists.txt +++ b/core/src/CMakeLists.txt @@ -1,2 +1,2 @@ add_subdirectory(exception) -add_subdirectory(loader) \ No newline at end of file +add_subdirectory(loader) diff --git a/core/src/loader/CMakeLists.txt b/core/src/loader/CMakeLists.txt index 92e7266..7b85e37 100644 --- a/core/src/loader/CMakeLists.txt +++ b/core/src/loader/CMakeLists.txt @@ -1,3 +1,3 @@ target_sources(arcade PRIVATE DLLoader.cpp -) \ No newline at end of file +) From a2804462127e534f12b543be70aac9a862847209 Mon Sep 17 00:00:00 2001 From: Yann Date: Fri, 22 Mar 2024 18:04:15 +0100 Subject: [PATCH 4/4] refactor(DLLoader): division of previous code into several methods --- core/src/loader/DLLoader.cpp | 71 ++++++++++++++++++++---------------- core/src/loader/DLLoader.hpp | 32 +++++++++++++--- core/src/types/Providers.hpp | 4 +- 3 files changed, 68 insertions(+), 39 deletions(-) diff --git a/core/src/loader/DLLoader.cpp b/core/src/loader/DLLoader.cpp index e9335fc..a31a2bd 100644 --- a/core/src/loader/DLLoader.cpp +++ b/core/src/loader/DLLoader.cpp @@ -12,45 +12,52 @@ #include "DLLoader.hpp" #include "exception/ArcadeError.hpp" -void DLLoader::registerLibrary(const std::string &path) { - void *handle = dlopen(path.c_str(), RTLD_LAZY); - shared::types::LibraryTypeGetter getter; +shared::types::LibraryType DLLoader::_getLibraryGetter(const std::string &filepath, void *handle) { + shared::types::LibraryTypeGetter getter = nullptr; + + getter = reinterpret_cast(dlsym(handle, SHARED_STRINGIFY(SHARED_LIBRARY_TYPE_GETTER_NAME))); + if (!getter) + throw ArcadeError("Cannot find library type getter in library: " + filepath); + return getter(); +} + +void DLLoader::_loadGameLibrary(const std::string &filepath, void *handle) { + shared::types::GameProvider game = nullptr; + + game = reinterpret_cast(dlsym(handle, SHARED_STRINGIFY(SHARED_GAME_PROVIDER_LOADER_NAME))); + if (!game) + throw ArcadeError("Cannot find game provider in library: " + filepath); + this->_gamesLibraries.push_back(game()); +} + +void DLLoader::_loadGraphicsLibrary(const std::string &filepath, void *handle) { + shared::types::GraphicsProvider graphics = nullptr; + + graphics = reinterpret_cast(dlsym(handle, SHARED_STRINGIFY(SHARED_GRAPHICS_PROVIDER_LOADER_NAME))); + if (!graphics) + throw ArcadeError("Cannot find graphics provider in library: " + filepath); + this->_graphicsLibraries.push_back(graphics()); +} + +void DLLoader::registerLibrary(const std::string &filepath) { + void *handle = dlopen(filepath.c_str(), RTLD_LAZY); shared::types::LibraryType type; - shared::types::GameProvider game; - shared::types::GraphicsProvider graphics; - std::cout << path << std::endl; if (!handle) - throw ArcadeError("Cannot load library: " + path); - getter = reinterpret_cast(dlsym(handle, SHARED_STRINGIFY(SHARED_LIBRARY_TYPE_GETTER_NAME))); - if (!getter) { - dlclose(handle); - throw ArcadeError("Cannot find getter in library: " + path); - } - type = getter(); - if (type == shared::types::LibraryType::GAME) { - game = reinterpret_cast(dlsym(handle, SHARED_STRINGIFY(SHARED_GAME_PROVIDER_LOADER_NAME))); - if (!game) { - dlclose(handle); - throw ArcadeError("Cannot find game provider in library: " + path); - } - this->_gamesLibraries.push_back(game()); - } - if (type == shared::types::LibraryType::GRAPHIC) { - graphics = reinterpret_cast(dlsym(handle, SHARED_STRINGIFY(SHARED_GRAPHICS_PROVIDER_LOADER_NAME))); - if (!graphics) { - dlclose(handle); - throw ArcadeError("Cannot find graphics provider in library: " + path); - } - this->_graphicsLibraries.push_back(graphics()); - } + throw ArcadeError("Cannot load library: " + filepath); + type = this->_getLibraryGetter(filepath, handle); + if (type == shared::types::LibraryType::GAME) + this->_loadGameLibrary(filepath, handle); + else if (type == shared::types::LibraryType::GRAPHIC) + this->_loadGraphicsLibrary(filepath, handle); + else + throw ArcadeError("Unknown library type: " + filepath); } void DLLoader::loadLibraries(std::string path) { DIR *dir; struct dirent *ent; - std::cout << path << std::endl; dir = opendir(path.c_str()); if (!dir) throw ArcadeError("Cannot open directory: " + path); @@ -66,10 +73,10 @@ void DLLoader::loadLibraries(std::string path) { closedir(dir); } -LoaderGamesProvider DLLoader::getGamesLibraries() const { +const GameProviders &DLLoader::getGamesLibraries() const { return this->_gamesLibraries; } -LoaderGraphicsProvider DLLoader::getGraphicsLibraries() const { +const GraphicsProviders &DLLoader::getGraphicsLibraries() const { return this->_graphicsLibraries; } diff --git a/core/src/loader/DLLoader.hpp b/core/src/loader/DLLoader.hpp index fd08420..ec7b363 100644 --- a/core/src/loader/DLLoader.hpp +++ b/core/src/loader/DLLoader.hpp @@ -17,7 +17,7 @@ class DLLoader { * @brief Register a library * @param path std::string */ - void registerLibrary(const std::string &path); + void registerLibrary(const std::string &filepath); /** * @brief Load all libraries in the given folder path @@ -29,16 +29,38 @@ class DLLoader { * @brief Get all games libraries * @return Loaded games libraries */ - LoaderGamesProvider getGamesLibraries() const; + const GameProviders &getGamesLibraries() const; /** * @brief Get all graphics libraries * @return Loaded graphics libraries */ - LoaderGraphicsProvider getGraphicsLibraries() const; + const GraphicsProviders &getGraphicsLibraries() const; private: const std::string _path; - LoaderGamesProvider _gamesLibraries; - LoaderGraphicsProvider _graphicsLibraries; + GameProviders _gamesLibraries; + GraphicsProviders _graphicsLibraries; + + /** + * @brief Get the Library Getter object + * @param filepath file path of the library + * @param handle handle pointer to the library + * @return getter function + */ + shared::types::LibraryType _getLibraryGetter(const std::string &filepath, void *handle); + + /** + * @brief Load a game library + * @param filepath file path of the library + * @param handle handle pointer to the library + */ + void _loadGameLibrary(const std::string &filepath, void *handle); + + /** + * @brief Load a graphics library + * @param filepath file path of the library + * @param handle handle pointer to the library + */ + void _loadGraphicsLibrary(const std::string &filepath, void *handle); }; diff --git a/core/src/types/Providers.hpp b/core/src/types/Providers.hpp index e157e32..7b7be0b 100644 --- a/core/src/types/Providers.hpp +++ b/core/src/types/Providers.hpp @@ -9,5 +9,5 @@ #include "common/types/Libraries.hpp" -typedef std::vector> LoaderGamesProvider; -typedef std::vector> LoaderGraphicsProvider; +typedef std::vector> GameProviders; +typedef std::vector> GraphicsProviders;