LibraryUtils.hpp (4104B)
1 /* 2 * DISTRHO Plugin Framework (DPF) 3 * Copyright (C) 2012-2021 Filipe Coelho <falktx@falktx.com> 4 * 5 * Permission to use, copy, modify, and/or distribute this software for any purpose with 6 * or without fee is hereby granted, provided that the above copyright notice and this 7 * permission notice appear in all copies. 8 * 9 * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES WITH REGARD 10 * TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS. IN 11 * NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL 12 * DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER 13 * IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN 14 * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. 15 */ 16 17 #ifndef DISTRHO_LIBRARY_UTILS_HPP_INCLUDED 18 #define DISTRHO_LIBRARY_UTILS_HPP_INCLUDED 19 20 #include "../DistrhoUtils.hpp" 21 22 #ifdef DISTRHO_OS_WINDOWS 23 # ifndef NOMINMAX 24 # define NOMINMAX 25 # endif 26 # include <winsock2.h> 27 # include <windows.h> 28 typedef HMODULE lib_t; 29 #else 30 # include <dlfcn.h> 31 typedef void* lib_t; 32 #endif 33 34 START_NAMESPACE_DISTRHO 35 36 // ----------------------------------------------------------------------- 37 // library related calls 38 39 /* 40 * Open 'filename' library (must not be null). 41 * May return null, in which case "lib_error" has the error. 42 */ 43 static inline 44 lib_t lib_open(const char* const filename) noexcept 45 { 46 DISTRHO_SAFE_ASSERT_RETURN(filename != nullptr && filename[0] != '\0', nullptr); 47 48 try { 49 #ifdef DISTRHO_OS_WINDOWS 50 return ::LoadLibraryA(filename); 51 #else 52 return ::dlopen(filename, RTLD_NOW|RTLD_LOCAL); 53 #endif 54 } DISTRHO_SAFE_EXCEPTION_RETURN("lib_open", nullptr); 55 } 56 57 /* 58 * Close a previously opened library (must not be null). 59 * If false is returned, "lib_error" has the error. 60 */ 61 static inline 62 bool lib_close(const lib_t lib) noexcept 63 { 64 DISTRHO_SAFE_ASSERT_RETURN(lib != nullptr, false); 65 66 try { 67 #ifdef DISTRHO_OS_WINDOWS 68 return ::FreeLibrary(lib); 69 #else 70 return (::dlclose(lib) == 0); 71 #endif 72 } DISTRHO_SAFE_EXCEPTION_RETURN("lib_close", false); 73 } 74 75 /* 76 * Get a library symbol (must not be null). 77 * Returns null if the symbol is not found. 78 */ 79 template<typename Func> 80 static inline 81 Func lib_symbol(const lib_t lib, const char* const symbol) noexcept 82 { 83 DISTRHO_SAFE_ASSERT_RETURN(lib != nullptr, nullptr); 84 DISTRHO_SAFE_ASSERT_RETURN(symbol != nullptr && symbol[0] != '\0', nullptr); 85 86 try { 87 #ifdef DISTRHO_OS_WINDOWS 88 # if defined(__GNUC__) && (__GNUC__ >= 9) 89 # pragma GCC diagnostic push 90 # pragma GCC diagnostic ignored "-Wcast-function-type" 91 # endif 92 return (Func)::GetProcAddress(lib, symbol); 93 # if defined(__GNUC__) && (__GNUC__ >= 9) 94 # pragma GCC diagnostic pop 95 # endif 96 #else 97 return (Func)(uintptr_t)::dlsym(lib, symbol); 98 #endif 99 } DISTRHO_SAFE_EXCEPTION_RETURN("lib_symbol", nullptr); 100 } 101 102 /* 103 * Return the last operation error ('filename' must not be null). 104 * May return null. 105 */ 106 static inline 107 const char* lib_error(const char* const filename) noexcept 108 { 109 DISTRHO_SAFE_ASSERT_RETURN(filename != nullptr && filename[0] != '\0', nullptr); 110 111 #ifdef DISTRHO_OS_WINDOWS 112 static char libError[2048+1]; 113 std::memset(libError, 0, sizeof(libError)); 114 115 try { 116 const DWORD winErrorCode = ::GetLastError(); 117 const int winErrorFlags = FORMAT_MESSAGE_ALLOCATE_BUFFER|FORMAT_MESSAGE_FROM_SYSTEM|FORMAT_MESSAGE_IGNORE_INSERTS; 118 LPVOID winErrorString; 119 120 ::FormatMessage(winErrorFlags, nullptr, winErrorCode, MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT), (LPTSTR)&winErrorString, 0, nullptr); 121 122 std::snprintf(libError, 2048, "%s: error code %li: %s", filename, winErrorCode, (const char*)winErrorString); 123 ::LocalFree(winErrorString); 124 } DISTRHO_SAFE_EXCEPTION("lib_error"); 125 126 return (libError[0] != '\0') ? libError : nullptr; 127 #else 128 return ::dlerror(); 129 #endif 130 } 131 132 // ----------------------------------------------------------------------- 133 134 END_NAMESPACE_DISTRHO 135 136 #endif // DISTRHO_LIBRARY_UTILS_HPP_INCLUDED