#ifndef LOADABLE_LIBRARY_MANAGER_H #define LOADABLE_LIBRARY_MANAGER_H #include #include #include #include #include #include #include #include #include namespace smo { namespace loadable_lib { class LoadableLibraryManager { public: struct SharedLibraryDeleter { void operator()(void* handle) const; }; struct LoadedSharedLibrary { LoadedSharedLibrary( std::string libraryPathIn, std::string resolvedPathIn, std::unique_ptr dlopenHandleIn) : libraryPath(std::move(libraryPathIn)), resolvedPath(std::move(resolvedPathIn)), dlopenHandle(std::move(dlopenHandleIn)) {} std::string libraryPath; std::string resolvedPath; std::unique_ptr dlopenHandle; std::atomic isBeingDestroyed{false}; void* getDlopenHandle() const { return dlopenHandle.get(); } std::string stringify() const { std::string result = "Library Path: " + libraryPath + "\n"; result += "Resolved Path: " + resolvedPath + "\n"; result += "Is Being Destroyed: "; result += (isBeingDestroyed.load() ? "true" : "false"); result += "\n"; return result; } }; struct Resources { std::vector> loadedSharedLibraries; }; static LoadableLibraryManager& getInstance() { static LoadableLibraryManager instance; return instance; } std::optional searchForLibInSmoSearchPaths( const std::string& libraryPath) const; std::shared_ptr loadSharedLibrary( const std::string& libraryPath); void unloadSharedLibrary( const std::shared_ptr& loadedLibrary); template static FnPtr resolveSymbol(void* handle, const char* symbolName) { dlerror(); auto symbol = reinterpret_cast(dlsym(handle, symbolName)); const char* dlerr = dlerror(); if (dlerr != nullptr) { throw std::runtime_error( std::string("dlsym('") + symbolName + "') failed: " + dlerr); } if (symbol == nullptr) { throw std::runtime_error( std::string("dlsym('") + symbolName + "') returned null"); } return symbol; } public: sscl::SharedResourceGroup s; private: LoadableLibraryManager() : s("LoadableLibraryManager") {} ~LoadableLibraryManager(); LoadableLibraryManager(const LoadableLibraryManager&) = delete; LoadableLibraryManager& operator=(const LoadableLibraryManager&) = delete; void appendLoadedSharedLibrary( const std::shared_ptr& loadedLibrary); void removeLoadedSharedLibrary( const std::shared_ptr& loadedLibrary); }; } // namespace loadable_lib } // namespace smo #endif // LOADABLE_LIBRARY_MANAGER_H