// SPDX-FileCopyrightText: 2019-2024 Connor McLaughlin <[email protected]>1// SPDX-License-Identifier: CC-BY-NC-ND-4.023#pragma once45#include <string>67class Error;89/**10* Provides a platform-independent interface for loading a dynamic library and retrieving symbols.11* The interface maintains an internal reference count to allow one handle to be shared between12* multiple users.13*/14class DynamicLibrary final15{16public:17/// Default constructor, does not load a library.18DynamicLibrary();1920/// Automatically loads the specified library. Call IsOpen() to check validity before use.21explicit DynamicLibrary(const char* filename);2223/// Move constructor, transfers ownership.24DynamicLibrary(DynamicLibrary&& move);2526/// Closes the library.27~DynamicLibrary();2829/// Returns the specified library name with the platform-specific suffix added.30static std::string GetUnprefixedFilename(const char* filename);3132/// Returns the specified library name in platform-specific format.33/// Major/minor versions will not be included if set to -1.34/// If libname already contains the "lib" prefix, it will not be added again.35/// Windows: LIBNAME-MAJOR-MINOR-PATCH.dll36/// Linux: libLIBNAME.so.MAJOR.MINOR.PATCH37/// Mac: libLIBNAME.MAJOR.MINOR.PATCH.dylib38static std::string GetVersionedFilename(const char* libname, int major = -1, int minor = -1, int patch = -1);3940/// Returns true if a module is loaded, otherwise false.41bool IsOpen() const { return m_handle != nullptr; }4243/// Loads (or replaces) the handle with the specified library file name.44/// Returns true if the library was loaded and can be used.45bool Open(const char* filename, Error* error);4647/// Adopts, or takes ownership of an existing opened library.48void Adopt(void* handle);4950/// Unloads the library, any function pointers from this library are no longer valid.51void Close();5253/// Returns the address of the specified symbol (function or variable) as an untyped pointer.54/// If the specified symbol does not exist in this library, nullptr is returned.55void* GetSymbolAddress(const char* name) const;5657/// Obtains the address of the specified symbol, automatically casting to the correct type.58/// Returns true if the symbol was found and assigned, otherwise false.59template<typename T>60bool GetSymbol(const char* name, T* ptr) const61{62*ptr = reinterpret_cast<T>(GetSymbolAddress(name));63return *ptr != nullptr;64}6566/// Returns the opaque OS-specific handle.67void* GetHandle() const { return m_handle; }6869/// Move assignment, transfer ownership.70DynamicLibrary& operator=(DynamicLibrary&& move);7172private:73DynamicLibrary(const DynamicLibrary&) = delete;74DynamicLibrary& operator=(const DynamicLibrary&) = delete;7576/// Platform-dependent data type representing a dynamic library handle.77void* m_handle = nullptr;78};798081