/home/runner/work/kynema/kynema/kynema/src/vendor/dylib/dylib.hpp Source File

Kynema API: /home/runner/work/kynema/kynema/kynema/src/vendor/dylib/dylib.hpp Source File
Kynema API
A flexible multibody structural dynamics code for wind turbines
Loading...
Searching...
No Matches
dylib.hpp
Go to the documentation of this file.
1
12#pragma once
13
14#include <stdexcept>
15#include <string>
16#include <utility>
17
18#if ((defined(_MSVC_LANG) && _MSVC_LANG >= 201703L) || __cplusplus >= 201703L)
19#define DYLIB_CPP17
20#include <filesystem>
21#endif
22
23#if (defined(_WIN32) || defined(_WIN64))
24#ifndef WIN32_LEAN_AND_MEAN
25#define WIN32_LEAN_AND_MEAN
26#define DYLIB_UNDEFINE_LEAN_AND_MEAN
27#endif
28#ifndef NOMINMAX
29#define NOMINMAX
30#define DYLIB_UNDEFINE_NOMINMAX
31#endif
32#include <windows.h>
33#ifdef DYLIB_UNDEFINE_LEAN_AND_MEAN
34#undef WIN32_LEAN_AND_MEAN
35#undef DYLIB_UNDEFINE_LEAN_AND_MEAN
36#endif
37#ifdef DYLIB_UNDEFINE_NOMINMAX
38#undef NOMINMAX
39#undef DYLIB_UNDEFINE_NOMINMAX
40#endif
41#else
42#include <dlfcn.h>
43#endif
44
45#if (defined(_WIN32) || defined(_WIN64)) // NOLINT
46#define DYLIB_WIN_MAC_OTHER(win_def, mac_def, other_def) win_def // NOLINT
47#define DYLIB_WIN_OTHER(win_def, other_def) win_def // NOLINT
48#elif defined(__APPLE__) // NOLINT
49#define DYLIB_WIN_MAC_OTHER(win_def, mac_def, other_def) mac_def // NOLINT
50#define DYLIB_WIN_OTHER(win_def, other_def) other_def // NOLINT
51#else // NOLINT
52#define DYLIB_WIN_MAC_OTHER(win_def, mac_def, other_def) other_def // NOLINT
53#define DYLIB_WIN_OTHER(win_def, other_def) other_def // NOLINT
54#endif // NOLINT
55
56namespace kynema::util {
57
62class dylib {
63public:
65 static constexpr const char* prefix = DYLIB_WIN_OTHER("", "lib");
66 static constexpr const char* suffix = DYLIB_WIN_MAC_OTHER(".dll", ".dylib", ".so");
67 };
68 using native_handle_type = DYLIB_WIN_OTHER(HINSTANCE, void*);
69 using native_symbol_type = DYLIB_WIN_OTHER(FARPROC, void*);
70
71 static_assert(std::is_pointer_v<native_handle_type>, "Expecting HINSTANCE to be a pointer");
72 static_assert(std::is_pointer_v<native_symbol_type>, "Expecting FARPROC to be a pointer");
73
74 static constexpr bool add_filename_decorations = true;
75 static constexpr bool no_filename_decorations = false;
76
80 class exception : public std::runtime_error {
81 using std::runtime_error::runtime_error;
82 };
83
87 class load_error : public exception {
88 using exception::exception;
89 };
90
94 class symbol_error : public exception {
95 using exception::exception;
96 };
97
98 dylib(const dylib&) = delete;
99 dylib& operator=(const dylib&) = delete;
100
101 dylib(dylib&& other) noexcept : m_handle(other.m_handle) { other.m_handle = nullptr; }
102
103 dylib& operator=(dylib&& other) noexcept {
104 if (this != &other) {
105 std::swap(m_handle, other.m_handle);
106 }
107 return *this;
108 }
109
122 dylib(const char* dir_path, const char* lib_name, bool decorations = add_filename_decorations) {
123 if (dir_path == nullptr) {
124 throw std::invalid_argument("The directory path is null");
125 }
126 if (lib_name == nullptr) {
127 throw std::invalid_argument("The library name is null");
128 }
129
130 std::string final_name = lib_name;
131 std::string final_path = dir_path;
132
133 if (decorations) {
135 }
136
137 if (!final_path.empty() && final_path.find_last_of('/') != final_path.size() - 1) {
138 final_path += '/';
139 }
140
141 m_handle = open((final_path + final_name).c_str());
142
143 if (m_handle == nullptr) {
144 throw load_error(
145 "Could not load library \"" + final_path + final_name + "\"\n" +
147 );
148 }
149 }
150
152 const std::string& dir_path, const std::string& lib_name,
153 bool decorations = add_filename_decorations
154 )
155 : dylib(dir_path.c_str(), lib_name.c_str(), decorations) {}
156
158 const std::string& dir_path, const char* lib_name,
159 bool decorations = add_filename_decorations
160 )
161 : dylib(dir_path.c_str(), lib_name, decorations) {}
162
164 const char* dir_path, const std::string& lib_name,
165 bool decorations = add_filename_decorations
166 )
167 : dylib(dir_path, lib_name.c_str(), decorations) {}
168
169 explicit dylib(const std::string& lib_name, bool decorations = add_filename_decorations)
170 : dylib("", lib_name.c_str(), decorations) {}
171
172 explicit dylib(const char* lib_name, bool decorations = add_filename_decorations)
173 : dylib("", lib_name, decorations) {}
174
175#ifdef DYLIB_CPP17
176 explicit dylib(const std::filesystem::path& lib_path)
177 : dylib("", lib_path.string().c_str(), no_filename_decorations) {}
178
179 dylib(
180 const std::filesystem::path& dir_path, const std::string& lib_name,
181 bool decorations = add_filename_decorations
182 )
183 : dylib(dir_path.string().c_str(), lib_name.c_str(), decorations) {}
184
185 dylib(
186 const std::filesystem::path& dir_path, const char* lib_name,
187 bool decorations = add_filename_decorations
188 )
189 : dylib(dir_path.string().c_str(), lib_name, decorations) {}
190#endif
192
194 if (m_handle != nullptr) {
196 }
197 }
198
209 native_symbol_type get_symbol(const char* symbol_name) const {
210 if (symbol_name == nullptr) {
211 throw std::invalid_argument("The symbol name to lookup is null");
212 }
213 if (m_handle == nullptr) {
214 throw std::logic_error(
215 "The dynamic library handle is null. This object may have been moved from."
216 );
217 }
218
219 auto* symbol = locate_symbol(m_handle, symbol_name);
220
221 if (symbol == nullptr) {
222 throw symbol_error(
223 "Could not get symbol \"" + std::string(symbol_name) + "\"\n" +
225 );
226 }
227 return symbol;
228 }
229
230 [[nodiscard]] native_symbol_type get_symbol(const std::string& symbol_name) const {
231 return get_symbol(symbol_name.c_str());
232 }
233
245 template <typename T>
246 T* get_function(const char* symbol_name) const {
247#if (defined(__GNUC__) && __GNUC__ >= 8)
248#pragma GCC diagnostic push
249#pragma GCC diagnostic ignored "-Wcast-function-type"
250#endif
251 return reinterpret_cast<T*>(get_symbol(symbol_name)); // NOLINT
252#if (defined(__GNUC__) && __GNUC__ >= 8)
253#pragma GCC diagnostic pop
254#endif
255 }
256
257 template <typename T>
258 T* get_function(const std::string& symbol_name) const { // NOLINT
259 return get_function<T>(symbol_name.c_str());
260 }
261
273 template <typename T>
274 T& get_variable(const char* symbol_name) const {
275 return *reinterpret_cast<T*>(get_symbol(symbol_name)); // NOLINT
276 }
277
278 template <typename T>
279 T& get_variable(const std::string& symbol_name) const {
280 return get_variable<T>(symbol_name.c_str());
281 }
282
292 [[nodiscard]] bool has_symbol(const char* symbol_name) const noexcept {
293 if (m_handle == nullptr || symbol_name == nullptr) {
294 return false;
295 }
296 return locate_symbol(m_handle, symbol_name) != nullptr;
297 }
298
299 [[nodiscard]] bool has_symbol(const std::string& symbol) const noexcept {
300 return has_symbol(symbol.c_str());
301 }
302
307
308protected:
310
311 static native_handle_type open(const char* path) noexcept {
312#if (defined(_WIN32) || defined(_WIN64))
313 return LoadLibraryA(path);
314#else
315 return dlopen(path, RTLD_NOW | RTLD_LOCAL);
316#endif
317 }
318
319 static native_symbol_type locate_symbol(native_handle_type lib, const char* name) noexcept {
320 return DYLIB_WIN_OTHER(GetProcAddress, dlsym)(lib, name);
321 }
322
323 static void close(native_handle_type lib) noexcept {
324 DYLIB_WIN_OTHER(FreeLibrary, dlclose)(lib);
325 }
326
327 static std::string get_error_description() {
328#if (defined(_WIN32) || defined(_WIN64))
329 constexpr const size_t BUF_SIZE = 512;
330 const auto error_code = GetLastError();
331 if (!error_code)
332 return "No error reported by GetLastError";
333 char description[BUF_SIZE];
334 const auto lang = MAKELANGID(LANG_ENGLISH, SUBLANG_ENGLISH_US);
335 const DWORD length = FormatMessageA(
336 FORMAT_MESSAGE_FROM_SYSTEM, nullptr, error_code, lang, description, BUF_SIZE, nullptr
337 );
338 return (length == 0) ? "Unknown error (FormatMessage failed)" : description;
339#else
340 const auto* const description = dlerror();
341 return (description == nullptr) ? "No error reported by dlerror" : description;
342#endif
343 }
344};
345
346#undef DYLIB_WIN_MAC_OTHER
347#undef DYLIB_WIN_OTHER
348#undef DYLIB_CPP17
349
350} // namespace kynema::util
Definition dylib.hpp:80
Definition dylib.hpp:87
Definition dylib.hpp:94
Definition dylib.hpp:62
T * get_function(const char *symbol_name) const
Definition dylib.hpp:246
bool has_symbol(const std::string &symbol) const noexcept
Definition dylib.hpp:299
~dylib()
Definition dylib.hpp:193
DYLIB_WIN_OTHER(FARPROC, void *) native_symbol_type
Definition dylib.hpp:69
dylib & operator=(dylib &&other) noexcept
Definition dylib.hpp:103
DYLIB_WIN_OTHER(HINSTANCE, void *) native_handle_type
Definition dylib.hpp:68
dylib(const std::string &lib_name, bool decorations=add_filename_decorations)
Definition dylib.hpp:169
dylib(const char *dir_path, const char *lib_name, bool decorations=add_filename_decorations)
Definition dylib.hpp:122
bool has_symbol(const char *symbol_name) const noexcept
Definition dylib.hpp:292
static constexpr bool add_filename_decorations
Definition dylib.hpp:74
dylib(const std::string &dir_path, const char *lib_name, bool decorations=add_filename_decorations)
Definition dylib.hpp:157
T & get_variable(const std::string &symbol_name) const
Definition dylib.hpp:279
dylib(const dylib &)=delete
dylib(const std::string &dir_path, const std::string &lib_name, bool decorations=add_filename_decorations)
Definition dylib.hpp:151
T & get_variable(const char *symbol_name) const
Definition dylib.hpp:274
native_handle_type m_handle
Definition dylib.hpp:309
dylib(dylib &&other) noexcept
Definition dylib.hpp:101
native_symbol_type get_symbol(const char *symbol_name) const
Definition dylib.hpp:209
native_handle_type native_handle() noexcept
Definition dylib.hpp:306
T * get_function(const std::string &symbol_name) const
Definition dylib.hpp:258
static constexpr bool no_filename_decorations
Definition dylib.hpp:75
static void close(native_handle_type lib) noexcept
Definition dylib.hpp:323
static native_handle_type open(const char *path) noexcept
Definition dylib.hpp:311
dylib & operator=(const dylib &)=delete
dylib(const char *dir_path, const std::string &lib_name, bool decorations=add_filename_decorations)
Definition dylib.hpp:163
native_symbol_type get_symbol(const std::string &symbol_name) const
Definition dylib.hpp:230
static std::string get_error_description()
Definition dylib.hpp:327
dylib(const char *lib_name, bool decorations=add_filename_decorations)
Definition dylib.hpp:172
static native_symbol_type locate_symbol(native_handle_type lib, const char *name) noexcept
Definition dylib.hpp:319
#define DYLIB_WIN_MAC_OTHER(win_def, mac_def, other_def)
Definition dylib.hpp:52
#define DYLIB_WIN_OTHER(win_def, other_def)
Definition dylib.hpp:53
Definition aerodyn_inflow.hpp:15
static constexpr const char * prefix
Definition dylib.hpp:65
static constexpr const char * suffix
Definition dylib.hpp:66