11#pragma once
22
33#include < cstddef>
4+ #include < string>
45
56#ifndef __EMSCRIPTEN__
67#ifdef _WIN32
@@ -113,6 +114,7 @@ class DynamicLibrary
113114
114115 if (names == nullptr )
115116 {
117+ m_lastError = " No library names provided" ;
116118 return false ;
117119 }
118120
@@ -125,15 +127,63 @@ class DynamicLibrary
125127 }
126128
127129#ifdef _WIN32
130+ ::SetLastError (0 );
128131 m_handle = ::LoadLibraryA (name);
129132#else
133+ ::dlerror (); // clear any prior error
130134 m_handle = ::dlopen (name, RTLD_LAZY | RTLD_LOCAL);
131135#endif
132136
133137 if (m_handle != nullptr )
134138 {
139+ m_loadedName = name;
140+ m_lastError.clear ();
135141 return true ;
136142 }
143+
144+ #ifdef _WIN32
145+ {
146+ const DWORD err = ::GetLastError ();
147+
148+ char * msg = nullptr ;
149+ const DWORD flags = FORMAT_MESSAGE_ALLOCATE_BUFFER | FORMAT_MESSAGE_FROM_SYSTEM | FORMAT_MESSAGE_IGNORE_INSERTS;
150+ const DWORD lang = MAKELANGID (LANG_NEUTRAL, SUBLANG_DEFAULT);
151+
152+ const DWORD len = ::FormatMessageA (flags,
153+ nullptr ,
154+ err,
155+ lang,
156+ reinterpret_cast <LPSTR>(&msg),
157+ 0 ,
158+ nullptr );
159+
160+ m_lastError = " LoadLibraryA failed for " ;
161+ m_lastError += name;
162+ m_lastError += " (" ;
163+ m_lastError += std::to_string (static_cast <unsigned long >(err));
164+ m_lastError += " ): " ;
165+ if (len != 0 && msg != nullptr )
166+ {
167+ m_lastError += msg;
168+ }
169+ if (msg != nullptr )
170+ {
171+ ::LocalFree (msg);
172+ }
173+ }
174+ #else
175+ {
176+ const char * err = ::dlerror ();
177+ m_lastError = " dlopen failed for " ;
178+ m_lastError += name;
179+ m_lastError += " : " ;
180+ if (err != nullptr )
181+ {
182+ m_lastError += err;
183+
184+ }
185+ }
186+ #endif
137187 }
138188
139189 return false ;
@@ -155,6 +205,8 @@ class DynamicLibrary
155205 ::dlclose (m_handle);
156206#endif
157207 m_handle = nullptr ;
208+ m_loadedName.clear ();
209+ m_lastError.clear ();
158210 }
159211
160212 /* *
@@ -165,6 +217,22 @@ class DynamicLibrary
165217 return m_handle != nullptr ;
166218 }
167219
220+ /* *
221+ * @brief Returns the name of the successfully opened library (empty if none).
222+ */
223+ [[nodiscard]] auto LoadedName () const -> const std::string&
224+ {
225+ return m_loadedName;
226+ }
227+
228+ /* *
229+ * @brief Returns the last error message from Open() (empty if none).
230+ */
231+ [[nodiscard]] auto LastError () const -> const std::string&
232+ {
233+ return m_lastError;
234+ }
235+
168236 /* *
169237 * @brief Returns the raw library handle.
170238 */
@@ -233,6 +301,8 @@ class DynamicLibrary
233301
234302private:
235303 LibHandle m_handle{}; // !< Library handle used to access the system library.
304+ std::string m_loadedName; // < Successfully opened library name.
305+ std::string m_lastError; // < Last Open() error message.
236306};
237307
238308/* *
0 commit comments