3434#include " SysError.h"
3535
3636#include < cbang/Exception.h>
37+ #include < cbang/String.h>
3738
3839#undef CBANG_EXCEPTION
3940#define CBANG_EXCEPTION DynamicLibraryException
@@ -53,67 +54,68 @@ using namespace cb;
5354bool DynamicLibrary::enabled = true ;
5455
5556
56- struct DynamicLibrary ::private_t {
57+ struct DynamicLibrary ::impl_t {
5758#ifdef _WIN32
5859 HMODULE handle;
59- #else
60- void *handle;
61- #endif
62- };
6360
61+ impl_t (const string &path) :
62+ handle(LoadLibraryEx(path.c_str(), 0, LOAD_LIBRARY_SEARCH_DEFAULT_DIRS)) {}
63+ ~impl_t () {if (handle) CloseHandle (handle);}
6464
65- DynamicLibrary::DynamicLibrary (const string &path) :
66- path(path), pri(new private_t ) {
65+ static void clear () {SysError::clear ();}
66+ string error () {return SysError ().toString ();}
67+ void *get (const string &name) {return GetProcAddress (handle, name.c_str ());}
6768
68- if (!enabled) THROW (" DynamicLibrary disabled globally" );
69+ #else // !_WIN32
70+ void *handle;
6971
70- #ifdef _WIN32
71- pri->handle =
72- LoadLibraryEx (path.c_str (), 0 , LOAD_LIBRARY_SEARCH_DEFAULT_DIRS);
73- if (!pri->handle )
74- THROW (" Failed to open dynamic library '" << path << " ': " << SysError ());
72+ impl_t (const string &path) : handle(dlopen(path.c_str(), RTLD_LAZY)) {}
73+ ~impl_t () {if (handle) dlclose (handle);}
7574
76- #else
77- dlerror (); // Clear errors
75+ static void clear () {dlerror ();} // Clear errors
76+ string error () {return dlerror ();}
77+ void *get (const string &name) {return dlsym (handle, name.c_str ());}
78+ #endif // !_WIN32
79+ };
7880
79- if (path.empty ()) THROW (" Library path is ''" );
8081
81- pri-> handle = dlopen ( path. c_str (), RTLD_LAZY);
82- if (!pri-> handle )
83- THROW ( " Failed to open dynamic library ' " << path << " ': " << dlerror ());
84- # endif
82+ DynamicLibrary::DynamicLibrary ( const string & path) :
83+ path(path), impl(load(path)) {
84+ if (!impl-> handle )
85+ THROW ( " Failed to open dynamic library ' " << path << " ': " << impl-> error ());
8586}
8687
8788
88- DynamicLibrary::~DynamicLibrary () {
89- #ifdef _WIN32
90- if (pri->handle ) CloseHandle (pri->handle );
89+ DynamicLibrary::DynamicLibrary (const vector<string> &paths) {
90+ for (auto &path: paths) {
91+ impl = load (this ->path = path);
92+ if (impl->handle ) return ;
93+ }
9194
92- #else
93- if (pri->handle ) dlclose (pri->handle );
94- #endif
95-
96- delete pri;
95+ THROW (" Failed to open any of the following dynamic libraries: "
96+ << String::join (paths, " , " ));
9797}
9898
9999
100+ DynamicLibrary::~DynamicLibrary () {}
101+
102+
100103void *DynamicLibrary::getSymbol (const string &name) {
101- #ifdef _WIN32
102- void *symbol = (void *)GetProcAddress (pri->handle , name.c_str ());
104+ impl_t::clear ();
105+ auto symbol = impl->get (name);
106+
103107 if (!symbol)
104108 THROW (" Failed to load dynamic symbol '" << name << " ' from library '"
105- << path << " ': " << SysError ());
109+ << path << " ': " << impl-> error ());
106110
107- # else
108- dlerror (); // Clear errors
111+ return symbol;
112+ }
109113
110- void *symbol = dlsym (pri->handle , name.c_str ());
111114
112- char *err = dlerror ();
113- if (err)
114- THROW (" Failed to load dynamic symbol '" << name << " ' from library '"
115- << path << " ': " << err);
116- #endif
115+ SmartPointer<DynamicLibrary::impl_t > DynamicLibrary::load (const string &path) {
116+ if (!enabled) THROW (" DynamicLibrary disabled globally" );
117+ if (path.empty ()) THROW (" Library path is ''" );
117118
118- return symbol;
119+ impl_t::clear ();
120+ return new impl_t (path);
119121}
0 commit comments