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..6e160ea 100644 --- a/core/main.cpp +++ b/core/main.cpp @@ -5,7 +5,18 @@ ** main */ +#include "loader/DLLoader.hpp" + int main(void) { + DLLoader loader; + + 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; + } return 0; } diff --git a/core/src/CMakeLists.txt b/core/src/CMakeLists.txt new file mode 100644 index 0000000..a72ba11 --- /dev/null +++ b/core/src/CMakeLists.txt @@ -0,0 +1,2 @@ +add_subdirectory(exception) +add_subdirectory(loader) 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..7b85e37 --- /dev/null +++ b/core/src/loader/CMakeLists.txt @@ -0,0 +1,3 @@ +target_sources(arcade PRIVATE + DLLoader.cpp +) diff --git a/core/src/loader/DLLoader.cpp b/core/src/loader/DLLoader.cpp new file mode 100644 index 0000000..a31a2bd --- /dev/null +++ b/core/src/loader/DLLoader.cpp @@ -0,0 +1,82 @@ +/* +** EPITECH PROJECT, 2024 +** arcade +** File description: +** DLLoader +*/ + +#include +#include +#include +#include +#include "DLLoader.hpp" +#include "exception/ArcadeError.hpp" + +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; + + if (!handle) + 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; + + dir = opendir(path.c_str()); + if (!dir) + throw ArcadeError("Cannot open directory: " + path); + 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); +} + +const GameProviders &DLLoader::getGamesLibraries() const { + return this->_gamesLibraries; +} + +const GraphicsProviders &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..ec7b363 --- /dev/null +++ b/core/src/loader/DLLoader.hpp @@ -0,0 +1,66 @@ +/* +** 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 &filepath); + + /** + * @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 + */ + const GameProviders &getGamesLibraries() const; + + /** + * @brief Get all graphics libraries + * @return Loaded graphics libraries + */ + const GraphicsProviders &getGraphicsLibraries() const; + + private: + const std::string _path; + 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 new file mode 100644 index 0000000..7b7be0b --- /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> GameProviders; +typedef std::vector> GraphicsProviders;