diff --git a/src/library_loader.h b/src/library_loader.h new file mode 100644 --- /dev/null +++ b/src/library_loader.h @@ -0,0 +1,112 @@ +/* + * This file is part of OpenTTD. + * OpenTTD is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, version 2. + * OpenTTD is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + * See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with OpenTTD. If not, see . + */ + +/** @file library_loader.h Functions/types related to loading libraries dynamically. */ + +#ifndef LIBRARY_LOADER_H +#define LIBRARY_LOADER_H + +class LibraryLoader { +public: + /** + * A function loaded from a library. + * + * Will automatically cast to the correct function pointer type on retrieval. + */ + class Function { + public: + explicit Function(void *p) : p(p) {} + + template >> + operator T *() const + { + return reinterpret_cast(this->p); + } + + private: + void *p; + }; + + /** + * Load a library with the given filename. + */ + explicit LibraryLoader(const std::string &filename) + { + this->handle = this->OpenLibrary(filename); + } + + /** + * Close the library. + */ + ~LibraryLoader() + { + if (this->handle != nullptr) { + this->CloseLibrary(); + } + } + + /** + * Check whether an error occurred while loading the library or a function. + * + * @return Whether an error occurred. + */ + bool HasError() + { + return this->error.has_value(); + } + + /** + * Get the last error that occurred while loading the library or a function. + * + * @return The error message. + */ + std::string GetLastError() + { + return this->error.value_or("No error"); + } + + /** + * Get a function from a loaded library. + * + * @param symbol_name The name of the function to get. + * @return The function. Check HasError() before using. + */ + Function GetFunction(const std::string &symbol_name) + { + if (this->error.has_value()) return Function(nullptr); + return Function(this->GetSymbol(symbol_name)); + } + +private: + /** + * Open the library with the given filename. + * + * Should set error if any error occurred. + * + * @param filename The filename of the library to open. + */ + void *OpenLibrary(const std::string &filename); + + /** + * Close the library. + */ + void CloseLibrary(); + + /** + * Get a symbol from the library. + * + * Should set error if any error occurred. + * + * @param symbol_name The name of the symbol to get. + */ + void *GetSymbol(const std::string &symbol_name); + + std::optional error = {}; ///< The last error that occurred, if set. + void *handle = nullptr; ///< Handle to the library. +}; + +#endif /* LIBRARY_LOADER_H */