OpenWalnut 1.3.1
|
00001 //--------------------------------------------------------------------------- 00002 // 00003 // Project: OpenWalnut ( http://www.openwalnut.org ) 00004 // 00005 // Copyright 2009 OpenWalnut Community, BSV@Uni-Leipzig and CNCF@MPI-CBS 00006 // For more information see http://www.openwalnut.org/copying 00007 // 00008 // This file is part of OpenWalnut. 00009 // 00010 // OpenWalnut is free software: you can redistribute it and/or modify 00011 // it under the terms of the GNU Lesser General Public License as published by 00012 // the Free Software Foundation, either version 3 of the License, or 00013 // (at your option) any later version. 00014 // 00015 // OpenWalnut is distributed in the hope that it will be useful, 00016 // but WITHOUT ANY WARRANTY; without even the implied warranty of 00017 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 00018 // GNU Lesser General Public License for more details. 00019 // 00020 // You should have received a copy of the GNU Lesser General Public License 00021 // along with OpenWalnut. If not, see <http://www.gnu.org/licenses/>. 00022 // 00023 //--------------------------------------------------------------------------- 00024 00025 #include <algorithm> 00026 #include <cassert> 00027 #include <string> 00028 00029 #ifdef _WIN32 00030 #include <iostream> 00031 #include <windows.h> // NOLINT 00032 #endif 00033 00034 #include <boost/filesystem.hpp> 00035 00036 #include "exceptions/WLibraryFetchFailed.h" 00037 #include "exceptions/WLibraryLoadFailed.h" 00038 #include "WSharedLib.h" 00039 00040 #ifdef _WIN32 00041 00042 /** 00043 * Simple class holding an opened library. 00044 */ 00045 struct WSharedLib::data 00046 { 00047 /** 00048 * Path of lib. 00049 */ 00050 const std::string m_path; 00051 00052 /** 00053 * Handle describing the loaded lib. 00054 */ 00055 HMODULE m_hDLL; 00056 00057 /** 00058 * Constructor. Opens and loads the library. 00059 * 00060 * \see WSharedLib::WSharedLib for details. 00061 * 00062 * \param path the lib to open 00063 */ 00064 explicit data( const std::string& path ): 00065 m_path( path ), 00066 m_hDLL( LoadLibrary( path.c_str() ) ) 00067 { 00068 if( !m_hDLL ) 00069 { 00070 throw WLibraryLoadFailed( std::string( "Could not load library \"" + m_path + "\" due to the error: " + errmsg() ) ); 00071 } 00072 } 00073 00074 /** 00075 * Destructor. Closes the previously opened library handle. 00076 */ 00077 ~data() 00078 { 00079 FreeLibrary( m_hDLL ); 00080 } 00081 00082 /** 00083 * Searches the lib for the specified function symbol and returns it. 00084 * 00085 * \param name the name of the function 00086 * 00087 * \return the pointer to the requested function 00088 * 00089 * \throw WLibraryFetchFailed thrown if the symbol could not be found. 00090 */ 00091 func_ptr_type findFunction( const std::string& name ) 00092 { 00093 func_ptr_type func_ptr = reinterpret_cast< func_ptr_type >( GetProcAddress( m_hDLL, name.c_str() ) ); 00094 if( !func_ptr ) 00095 { 00096 throw WLibraryFetchFailed( std::string( "Could not fetch symbol \"" + name + "\"" + " due to the error: " + errmsg() ) ); 00097 } 00098 return func_ptr; 00099 } 00100 00101 /** 00102 * Searches the lib for the specified function symbol and returns it. 00103 * 00104 * \param name the name of the function 00105 * 00106 * \return the pointer to the requested function 00107 * 00108 * \throw WLibraryFetchFailed thrown if the symbol could not be found. 00109 */ 00110 void* findVariable( const std::string& name ) 00111 { 00112 return reinterpret_cast< void* >( findFunction( name ) ); 00113 } 00114 00115 /** 00116 * Constructs a nice looking error message for the last error occurred. 00117 * 00118 * \return the last error message 00119 */ 00120 static std::string errmsg() 00121 { 00122 std::string msg; 00123 LPTSTR lpMsgBuf = 0; 00124 FormatMessage( FORMAT_MESSAGE_ALLOCATE_BUFFER | FORMAT_MESSAGE_FROM_SYSTEM | FORMAT_MESSAGE_IGNORE_INSERTS, 0, GetLastError(), 0, 00125 reinterpret_cast< LPTSTR >( &lpMsgBuf ), 0, 0 ); 00126 LPTSTR p = lpMsgBuf; 00127 while( *p ) 00128 { 00129 msg.push_back( *p++ ); 00130 } 00131 LocalFree( lpMsgBuf ); 00132 return msg; 00133 } 00134 }; 00135 #else 00136 #include <dlfcn.h> // NOLINT 00137 #include <pthread.h> // NOLINT 00138 00139 namespace 00140 { 00141 pthread_mutex_t mutex = PTHREAD_MUTEX_INITIALIZER; 00142 struct auto_lock 00143 { 00144 auto_lock() 00145 { 00146 pthread_mutex_lock( &mutex ); 00147 } 00148 ~auto_lock() 00149 { 00150 pthread_mutex_unlock( &mutex ); 00151 } 00152 }; 00153 } 00154 00155 /** 00156 * Simple class holding an opened library. 00157 */ 00158 struct WSharedLib::data 00159 { 00160 /** 00161 * Path of lib. 00162 */ 00163 const std::string m_path; 00164 00165 /** 00166 * Handle describing the loaded lib. 00167 */ 00168 void* m_dl; 00169 00170 /** 00171 * Destructor. Closes the previously opened library handle. 00172 */ 00173 ~data() 00174 { 00175 assert( dlclose( m_dl ) == 0 ); 00176 } 00177 00178 /** 00179 * Constructor. Opens and loads the library. 00180 * 00181 * \see WSharedLib::WSharedLib for details. 00182 * 00183 * \param path the lib to open 00184 */ 00185 explicit data( const std::string& path ) 00186 : m_path( path ), m_dl( 0 ) 00187 { 00188 auto_lock lock; 00189 m_dl = dlopen( m_path.c_str(), RTLD_LAZY ); 00190 if( !m_dl ) 00191 { 00192 throw WLibraryLoadFailed( std::string( "Could not load library \"" + m_path + "\" due to the error: " + dlerror() ) ); 00193 } 00194 } 00195 00196 /** 00197 * Searches the lib for the specified function symbol and returns it. 00198 * 00199 * \param name the name of the function 00200 * 00201 * \return the pointer to the requested function 00202 * 00203 * \throw WLibraryFetchFailed thrown if the symbol could not be found. 00204 */ 00205 func_ptr_type findFunction( const std::string& name ) 00206 { 00207 // This cast is supposed to throw a warning because the cast 00208 // of void* to function pointers is not defined or required 00209 // in ISO C. Nevertheless, it works on most current compilers. 00210 // 00211 // man dlsym talks about introducing a new function to circumvent 00212 // this problem. 00213 return reinterpret_cast< func_ptr_type >( findVariable( name ) ); 00214 } 00215 00216 /** 00217 * Searches the lib for the specified symbol and returns it. 00218 * 00219 * \param name the name of the symbol to search. 00220 * 00221 * \return pointer to the symbol. 00222 * 00223 * \throw WLibraryFetchFailed thrown if the symbol could not be found. 00224 * 00225 */ 00226 void* findVariable( const std::string& name ) 00227 { 00228 auto_lock lock; 00229 dlerror(); 00230 void* variable_ptr = dlsym( m_dl, name.c_str() ); 00231 const char *err = dlerror(); 00232 if( err ) 00233 { 00234 throw WLibraryFetchFailed( std::string( "Could not fetch symbol \"" + name + "\"" + " due to the error: " + err ) ); 00235 } 00236 return variable_ptr; 00237 } 00238 }; 00239 #endif 00240 00241 WSharedLib::WSharedLib( boost::filesystem::path lib ): 00242 m_data( new data( lib.string() ) ) 00243 { 00244 } 00245 00246 WSharedLib::WSharedLib( const WSharedLib& rhs ): 00247 m_data( new data( rhs.m_data->m_path ) ) 00248 { 00249 } 00250 00251 WSharedLib::~WSharedLib() 00252 { 00253 delete m_data; 00254 } 00255 00256 WSharedLib& WSharedLib::operator=( const WSharedLib& rhs ) 00257 { 00258 WSharedLib o( rhs ); 00259 swap( *this, o ); 00260 return *this; 00261 } 00262 00263 void swap( WSharedLib& lhs, WSharedLib& rhs ) 00264 { 00265 std::swap( lhs.m_data, rhs.m_data ); 00266 } 00267 00268 WSharedLib::func_ptr_type WSharedLib::findFunction( const std::string& name ) const 00269 { 00270 return m_data->findFunction( name ); 00271 } 00272 00273 void* WSharedLib::findVariable( const std::string& name ) const 00274 { 00275 return m_data->findVariable( name ); 00276 } 00277 00278 std::string WSharedLib::getSystemPrefix() 00279 { 00280 return W_LIB_PREFIX; 00281 } 00282 00283 std::string WSharedLib::getSystemSuffix() 00284 { 00285 return W_LIB_SUFFIX; 00286 } 00287 00288 std::string WSharedLib::getSystemLibPath() 00289 { 00290 return "../lib"; 00291 } 00292