OpenWalnut  1.2.5
 All Classes Namespaces Functions Variables Typedefs Enumerations Enumerator Friends
WSharedLib.cpp
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 
 All Classes Namespaces Functions Variables Typedefs Enumerations Enumerator Friends