OpenWalnut
1.2.5
|
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 // Use filesystem version 2 for compatibility with newer boost versions. 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 * Simple class holding an opened library. 00048 */ 00049 struct WSharedLib::data 00050 { 00051 /** 00052 * Path of lib. 00053 */ 00054 const std::string m_path; 00055 00056 /** 00057 * Handle describing the loaded lib. 00058 */ 00059 HMODULE m_hDLL; 00060 00061 /** 00062 * Constructor. Opens and loads the library. 00063 * 00064 * \see WSharedLib::WSharedLib for details. 00065 * 00066 * \param path the lib to open 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 * Destructor. Closes the previously opened library handle. 00080 */ 00081 ~data() 00082 { 00083 FreeLibrary( m_hDLL ); 00084 } 00085 00086 /** 00087 * Searches the lib for the specified function symbol and returns it. 00088 * 00089 * \param name the name of the function 00090 * 00091 * \return the pointer to the requested function 00092 * 00093 * \throw WLibraryFetchFailed thrown if the symbol could not be found. 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 * Searches the lib for the specified function symbol and returns it. 00107 * 00108 * \param name the name of the function 00109 * 00110 * \return the pointer to the requested function 00111 * 00112 * \throw WLibraryFetchFailed thrown if the symbol could not be found. 00113 */ 00114 void* findVariable( const std::string& name ) 00115 { 00116 return reinterpret_cast< void* >( findFunction( name ) ); 00117 } 00118 00119 /** 00120 * Constructs a nice looking error message for the last error occurred. 00121 * 00122 * \return the last error message 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> // NOLINT 00141 #include <pthread.h> // NOLINT 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 * Simple class holding an opened library. 00161 */ 00162 struct WSharedLib::data 00163 { 00164 /** 00165 * Path of lib. 00166 */ 00167 const std::string m_path; 00168 00169 /** 00170 * Handle describing the loaded lib. 00171 */ 00172 void* m_dl; 00173 00174 /** 00175 * Destructor. Closes the previously opened library handle. 00176 */ 00177 ~data() 00178 { 00179 assert( dlclose( m_dl ) == 0 ); 00180 } 00181 00182 /** 00183 * Constructor. Opens and loads the library. 00184 * 00185 * \see WSharedLib::WSharedLib for details. 00186 * 00187 * \param path the lib to open 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 * Searches the lib for the specified function symbol and returns it. 00202 * 00203 * \param name the name of the function 00204 * 00205 * \return the pointer to the requested function 00206 * 00207 * \throw WLibraryFetchFailed thrown if the symbol could not be found. 00208 */ 00209 func_ptr_type findFunction( const std::string& name ) 00210 { 00211 return reinterpret_cast< func_ptr_type >( findVariable( name ) ); 00212 } 00213 00214 /** 00215 * Searches the lib for the specified symbol and returns it. 00216 * 00217 * \param name the name of the symbol to search. 00218 * 00219 * \return pointer to the symbol. 00220 * 00221 * \throw WLibraryFetchFailed thrown if the symbol could not be found. 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 // easier this way because VC has problems with quote in command line. So we can not get this information by #define from CMake. 00278 // Maybe you have to spend another 500 bucks to have your VC support nearly trivial stuff. 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