Line data Source code
1 : // Author(s): Jeroen Keiren, Sjoerd Cranen 2 : // Copyright: see the accompanying file COPYING or copy at 3 : // https://github.com/mCRL2org/mCRL2/blob/master/COPYING 4 : // 5 : // Distributed under the Boost Software License, Version 1.0. 6 : // (See accompanying file LICENSE_1_0.txt or copy at 7 : // http://www.boost.org/LICENSE_1_0.txt) 8 : // 9 : /// \file mcrl2/utilities/dynamic_library.h 10 : 11 : 12 : #ifndef MCRL2_UTILITIES_DYNAMIC_LIBRARY_H 13 : #define MCRL2_UTILITIES_DYNAMIC_LIBRARY_H 14 : 15 : #include "mcrl2/utilities/logger.h" 16 : #include "mcrl2/utilities/platform.h" 17 : 18 : #ifdef MCRL2_PLATFORM_WINDOWS 19 : #include <windows.h> 20 : typedef HMODULE library_handle; 21 : typedef FARPROC library_proc; 22 : 23 : inline 24 : library_handle get_module_handle(const std::string& fname) 25 : { 26 : return LoadLibrary(fname.c_str()); 27 : } 28 : 29 : inline 30 : library_proc get_proc_address(library_handle handle, const std::string& procname) 31 : { 32 : return GetProcAddress(handle, procname.c_str()); 33 : } 34 : 35 : inline 36 : bool close_module_handle(library_handle handle) 37 : { 38 : return FreeLibrary(handle); 39 : } 40 : 41 : inline 42 : std::string get_last_error() 43 : { 44 : std::string result; 45 : char *buffer = 0; 46 : DWORD last = GetLastError(); 47 : DWORD x = FormatMessage( 48 : FORMAT_MESSAGE_ALLOCATE_BUFFER | // Let Windows allocate string 49 : FORMAT_MESSAGE_FROM_SYSTEM, // Retrieve a system error message 50 : nullptr, // No source needed 51 : last, // Requested error message 52 : 0, // Default language 53 : reinterpret_cast<LPSTR>(&buffer), // Output buffer 54 : 0, // Minimum allocation size 55 : nullptr // No arguments here 56 : ); 57 : if (x) 58 : { 59 : result = buffer; 60 : } 61 : else 62 : { 63 : result = "Unknown error."; 64 : } 65 : LocalFree(buffer); 66 : return result; 67 : } 68 : #else 69 : #include <dlfcn.h> 70 : typedef void* library_handle; 71 : typedef void* library_proc; 72 : 73 : inline 74 5 : library_handle get_module_handle(const std::string& fname) 75 : { 76 : // return dlopen(fname.c_str(), RTLD_LAZY); 77 5 : return dlopen(fname.c_str(), RTLD_NOW); 78 : } 79 : 80 : inline 81 5 : library_proc get_proc_address(library_handle handle, const std::string& procname) 82 : { 83 5 : return dlsym(handle, procname.c_str()); 84 : } 85 : 86 : inline 87 5 : bool close_module_handle(library_handle handle) 88 : { 89 5 : return (dlclose(handle) == 0); 90 : } 91 : 92 : inline 93 0 : std::string get_last_error() 94 : { 95 0 : return std::string(dlerror()); 96 : } 97 : #endif 98 : 99 : class dynamic_library 100 : { 101 : protected: 102 : library_handle m_library; 103 : std::string m_filename; 104 : 105 5 : void load() 106 : { 107 5 : if (m_library == nullptr) 108 : { 109 5 : m_library = get_module_handle(m_filename.c_str()); 110 5 : if (m_library == nullptr) 111 : { 112 0 : throw std::runtime_error("Could not load library (" + m_filename + "): " + get_last_error()); 113 : } 114 : } 115 5 : } 116 : 117 5 : void unload() 118 : { 119 5 : if (m_library!=nullptr) 120 : { 121 5 : if (!close_module_handle(m_library)) 122 : { 123 0 : throw std::runtime_error("Could not close library (" + m_filename + "): " + get_last_error()); 124 : } 125 5 : m_library = nullptr; 126 : } 127 5 : } 128 : 129 : public: 130 5 : dynamic_library(const std::string& filename = std::string()) 131 5 : : m_library(nullptr), 132 5 : m_filename(filename) 133 : { 134 5 : } 135 : 136 5 : virtual ~dynamic_library() 137 5 : { 138 : try 139 : { 140 5 : unload(); 141 : } 142 0 : catch(std::runtime_error& error) 143 : { 144 0 : mCRL2log(mcrl2::log::error) << "Error while unloading dynamic library: " << error.what() << std::endl; 145 0 : } 146 5 : } 147 : 148 5 : library_proc proc_address(const std::string& name) 149 : { 150 5 : if (m_library == nullptr) 151 : { 152 5 : load(); 153 : } 154 5 : library_proc result = get_proc_address(m_library, name.c_str()); 155 5 : if (result == 0) 156 : { 157 0 : throw std::runtime_error("Could not find proc address (" + m_filename + ":" + name + "): " + get_last_error()); 158 : } 159 5 : return result; 160 : } 161 : }; 162 : 163 : #endif // MCRL2_UTILITIES_DYNAMIC_LIBRARY_H