00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025 #include <algorithm>
00026 #include <cassert>
00027 #include <string>
00028
00029 #ifdef _WIN32
00030 #include <iostream>
00031 #include <windows.h>
00032 #endif
00033
00034
00035 #ifndef BOOST_FILESYSTEM_VERSION
00036 #define BOOST_FILESYSTEM_VERSION 2
00037 #endif
00038 #include <boost/filesystem.hpp>
00039
00040 #include "exceptions/WLibraryFetchFailed.h"
00041 #include "exceptions/WLibraryLoadFailed.h"
00042 #include "WSharedLib.h"
00043
00044 #ifdef _WIN32
00045
00046
00047
00048
00049 struct WSharedLib::data
00050 {
00051
00052
00053
00054 const std::string m_path;
00055
00056
00057
00058
00059 HMODULE m_hDLL;
00060
00061
00062
00063
00064
00065
00066
00067
00068 explicit data( const std::string& path ):
00069 m_path( path ),
00070 m_hDLL( LoadLibrary( path.c_str() ) )
00071 {
00072 if( !m_hDLL )
00073 {
00074 throw WLibraryLoadFailed( std::string( "Could not load library \"" + m_path + "\" due to the error: " + errmsg() ) );
00075 }
00076 }
00077
00078
00079
00080
00081 ~data()
00082 {
00083 FreeLibrary( m_hDLL );
00084 }
00085
00086
00087
00088
00089
00090
00091
00092
00093
00094
00095 func_ptr_type findFunction( const std::string& name )
00096 {
00097 func_ptr_type func_ptr = reinterpret_cast< func_ptr_type >( GetProcAddress( m_hDLL, name.c_str() ) );
00098 if( !func_ptr )
00099 {
00100 throw WLibraryFetchFailed( std::string( "Could not fetch symbol \"" + name + "\"" + " due to the error: " + errmsg() ) );
00101 }
00102 return func_ptr;
00103 }
00104
00105
00106
00107
00108
00109
00110
00111
00112
00113
00114 void* findVariable( const std::string& name )
00115 {
00116 return reinterpret_cast< void* >( findFunction( name ) );
00117 }
00118
00119
00120
00121
00122
00123
00124 static std::string errmsg()
00125 {
00126 std::string msg;
00127 LPTSTR lpMsgBuf = 0;
00128 FormatMessage( FORMAT_MESSAGE_ALLOCATE_BUFFER | FORMAT_MESSAGE_FROM_SYSTEM | FORMAT_MESSAGE_IGNORE_INSERTS, 0, GetLastError(), 0,
00129 reinterpret_cast< LPTSTR >( &lpMsgBuf ), 0, 0 );
00130 LPTSTR p = lpMsgBuf;
00131 while( *p )
00132 {
00133 msg.push_back( *p++ );
00134 }
00135 LocalFree( lpMsgBuf );
00136 return msg;
00137 }
00138 };
00139 #else
00140 #include <dlfcn.h>
00141 #include <pthread.h>
00142
00143 namespace
00144 {
00145 pthread_mutex_t mutex = PTHREAD_MUTEX_INITIALIZER;
00146 struct auto_lock
00147 {
00148 auto_lock()
00149 {
00150 pthread_mutex_lock( &mutex );
00151 }
00152 ~auto_lock()
00153 {
00154 pthread_mutex_unlock( &mutex );
00155 }
00156 };
00157 }
00158
00159
00160
00161
00162 struct WSharedLib::data
00163 {
00164
00165
00166
00167 const std::string m_path;
00168
00169
00170
00171
00172 void* m_dl;
00173
00174
00175
00176
00177 ~data()
00178 {
00179 assert( dlclose( m_dl ) == 0 );
00180 }
00181
00182
00183
00184
00185
00186
00187
00188
00189 explicit data( const std::string& path )
00190 : m_path( path ), m_dl( 0 )
00191 {
00192 auto_lock lock();
00193 m_dl = dlopen( m_path.c_str(), RTLD_LAZY );
00194 if( !m_dl )
00195 {
00196 throw WLibraryLoadFailed( std::string( "Could not load library \"" + m_path + "\" due to the error: " + dlerror() ) );
00197 }
00198 }
00199
00200
00201
00202
00203
00204
00205
00206
00207
00208
00209 func_ptr_type findFunction( const std::string& name )
00210 {
00211 return reinterpret_cast< func_ptr_type >( findVariable( name ) );
00212 }
00213
00214
00215
00216
00217
00218
00219
00220
00221
00222
00223
00224 void* findVariable( const std::string& name )
00225 {
00226 auto_lock lock();
00227 dlerror();
00228 void* variable_ptr = dlsym( m_dl, name.c_str() );
00229 const char *err = dlerror();
00230 if( err )
00231 {
00232 throw WLibraryFetchFailed( std::string( "Could not fetch symbol \"" + name + "\"" + " due to the error: " + err ) );
00233 }
00234 return variable_ptr;
00235 }
00236 };
00237 #endif
00238
00239 WSharedLib::WSharedLib( boost::filesystem::path lib ):
00240 m_data( new data( lib.native_file_string() ) )
00241 {
00242 }
00243
00244 WSharedLib::WSharedLib( const WSharedLib& rhs ):
00245 m_data( new data( rhs.m_data->m_path ) )
00246 {
00247 }
00248
00249 WSharedLib::~WSharedLib()
00250 {
00251 delete m_data;
00252 }
00253
00254 WSharedLib& WSharedLib::operator=( const WSharedLib& rhs )
00255 {
00256 WSharedLib o( rhs );
00257 swap( *this, o );
00258 return *this;
00259 }
00260
00261 void swap( WSharedLib& lhs, WSharedLib& rhs )
00262 {
00263 std::swap( lhs.m_data, rhs.m_data );
00264 }
00265
00266 WSharedLib::func_ptr_type WSharedLib::findFunction( const std::string& name ) const
00267 {
00268 return m_data->findFunction( name );
00269 }
00270
00271 void* WSharedLib::findVariable( const std::string& name ) const
00272 {
00273 return m_data->findVariable( name );
00274 }
00275
00276 #ifdef _MSC_VER
00277
00278
00279 std::string WSharedLib::getSystemPrefix()
00280 {
00281 return "";
00282 }
00283
00284 std::string WSharedLib::getSystemSuffix()
00285 {
00286 return ".dll";
00287 }
00288 #else
00289 std::string WSharedLib::getSystemPrefix()
00290 {
00291 return W_LIB_PREFIX;
00292 }
00293
00294 std::string WSharedLib::getSystemSuffix()
00295 {
00296 return W_LIB_SUFFIX;
00297 }
00298 #endif
00299
00300 std::string WSharedLib::getSystemLibPath()
00301 {
00302 return "../lib";
00303 }
00304