// // ██████ ██  ██  ██████  ██████ // ██      ██  ██ ██    ██ ██       ** Classy Header-Only Classes ** // ██  ███████ ██  ██ ██ // ██  ██   ██ ██  ██ ██ https://github.com/Tracktion/choc //  ██████ ██  ██  ██████   ██████ // // CHOC is (C)2022 Tracktion Corporation, and is offered under the terms of the ISC license: // // Permission to use, copy, modify, and/or distribute this software for any purpose with or // without fee is hereby granted, provided that the above copyright notice and this permission // notice appear in all copies. THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL // WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY // AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR // CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, // WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN // CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. #ifndef CHOC_DYNAMIC_LIBRARY_HEADER_INCLUDED #define CHOC_DYNAMIC_LIBRARY_HEADER_INCLUDED #include START_NAMESPACE_DISTRHO //============================================================================== /** A minimal cross-platform loader for .dll/.so files. */ struct DynamicLibrary { DynamicLibrary() = default; /// Attempts to load a library with the given name or path. DynamicLibrary (std::string_view library); DynamicLibrary (const DynamicLibrary&) = delete; DynamicLibrary& operator= (const DynamicLibrary&) = delete; DynamicLibrary (DynamicLibrary&&); DynamicLibrary& operator= (DynamicLibrary&&); /// On destruction, this object releases the library that was loaded ~DynamicLibrary(); /// Returns a pointer to the function with this name, or nullptr if not found. void* findFunction (std::string_view functionName); /// Returns true if the library was successfully loaded operator bool() const noexcept { return handle != nullptr; } /// Releases any handle that this object is holding void close(); /// platform-specific handle. Will be nullptr if not loaded void* handle = nullptr; }; //============================================================================== // _ _ _ _ // __| | ___ | |_ __ _ (_)| | ___ // / _` | / _ \| __| / _` || || |/ __| // | (_| || __/| |_ | (_| || || |\__ \ _ _ _ // \__,_| \___| \__| \__,_||_||_||___/(_)(_)(_) // // Code beyond this point is implementation detail... // //============================================================================== inline DynamicLibrary::~DynamicLibrary() { close(); } inline DynamicLibrary::DynamicLibrary (DynamicLibrary&& other) : handle (other.handle) { other.handle = nullptr; } inline DynamicLibrary& DynamicLibrary::operator= (DynamicLibrary&& other) { close(); handle = other.handle; other.handle = nullptr; return *this; } //============================================================================== namespace win32_defs { #if ! (defined (_WINDOWS_) || defined (_APISETLIBLOADER_)) // only use these local definitions if windows.h isn't already included using CHOC_HMODULE = void*; #ifdef _MSC_VER extern "C" CHOC_HMODULE __stdcall choc_LoadLibraryA (const char*); extern "C" int __stdcall choc_FreeLibrary (CHOC_HMODULE); extern "C" void* __stdcall choc_GetProcAddress (CHOC_HMODULE, const char*); #pragma comment(linker,"/alternatename:choc_LoadLibraryA=LoadLibraryA") #pragma comment(linker,"/alternatename:choc_FreeLibrary=FreeLibrary") #pragma comment(linker,"/alternatename:choc_GetProcAddress=GetProcAddress") static inline CHOC_HMODULE LoadLibraryA (const char* l) { return choc_LoadLibraryA (l); } static inline int FreeLibrary (CHOC_HMODULE m) { return choc_FreeLibrary (m); } static inline void* GetProcAddress (CHOC_HMODULE m, const char* f) { return choc_GetProcAddress (m, f); } #else extern "C" __declspec(dllimport) CHOC_HMODULE __stdcall LoadLibraryA (const char*); extern "C" __declspec(dllimport) int __stdcall FreeLibrary (CHOC_HMODULE); extern "C" __declspec(dllimport) void* __stdcall GetProcAddress (CHOC_HMODULE, const char*); #endif #else using CHOC_HMODULE = HMODULE; static inline CHOC_HMODULE LoadLibraryA (const char* l) { return ::LoadLibraryA (l); } static inline int FreeLibrary (CHOC_HMODULE m) { return ::FreeLibrary (m); } static inline void* GetProcAddress (CHOC_HMODULE m, const char* f) { return (void*) ::GetProcAddress (m, f); } #endif } inline DynamicLibrary::DynamicLibrary (std::string_view library) { handle = (void*) win32_defs::LoadLibraryA (std::string (library).c_str()); } inline void DynamicLibrary::close() { if (handle != nullptr) { win32_defs::FreeLibrary ((win32_defs::CHOC_HMODULE) handle); handle = nullptr; } } inline void* DynamicLibrary::findFunction (std::string_view name) { if (handle != nullptr) return (void*) win32_defs::GetProcAddress ((win32_defs::CHOC_HMODULE) handle, std::string (name).c_str()); return {}; } END_NAMESPACE_DISTRHO #endif // CHOC_DYNAMIC_LIBRARY_HEADER_INCLUDED