OpenWalnut  1.4.0
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 #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      * Check for existence of a given function pointer symbol.
00103      *
00104      * \param name the symbol
00105      *
00106      * \return true if it exists.
00107      */
00108     bool existsFunction( const std::string& name )
00109     {
00110         func_ptr_type func_ptr = reinterpret_cast< func_ptr_type >( GetProcAddress( m_hDLL, name.c_str() ) );
00111         return func_ptr;
00112     }
00113 
00114     /**
00115      * Searches the lib for the specified function symbol and returns it.
00116      *
00117      * \param name the name of the function
00118      *
00119      * \return the pointer to the requested function
00120      *
00121      * \throw WLibraryFetchFailed thrown if the symbol could not be found.
00122      */
00123     void* findVariable( const std::string& name )
00124     {
00125         return reinterpret_cast< void* >( findFunction( name ) );
00126     }
00127 
00128     /**
00129      * Constructs a nice looking error message for the last error occurred.
00130      *
00131      * \return the last error message
00132      */
00133     static std::string errmsg()
00134     {
00135         std::string msg;
00136         LPTSTR lpMsgBuf = 0;
00137         FormatMessage( FORMAT_MESSAGE_ALLOCATE_BUFFER | FORMAT_MESSAGE_FROM_SYSTEM | FORMAT_MESSAGE_IGNORE_INSERTS, 0, GetLastError(), 0,
00138                        reinterpret_cast< LPTSTR >( &lpMsgBuf ), 0, 0 );
00139         LPTSTR p = lpMsgBuf;
00140         while( *p )
00141         {
00142             msg.push_back( *p++ );
00143         }
00144         LocalFree( lpMsgBuf );
00145         return msg;
00146     }
00147 };
00148 #else
00149 #include <dlfcn.h>      // NOLINT
00150 #include <pthread.h>    // NOLINT
00151 
00152 namespace
00153 {
00154     pthread_mutex_t mutex = PTHREAD_MUTEX_INITIALIZER;
00155     struct auto_lock
00156     {
00157         auto_lock()
00158         {
00159             pthread_mutex_lock( &mutex );
00160         }
00161         ~auto_lock()
00162         {
00163             pthread_mutex_unlock( &mutex );
00164         }
00165     };
00166 }
00167 
00168 /**
00169  * Simple class holding an opened library.
00170  */
00171 struct WSharedLib::data
00172 {
00173     /**
00174      * Path of lib.
00175      */
00176     const std::string m_path;
00177 
00178     /**
00179      * Handle describing the loaded lib.
00180      */
00181     void* m_dl;
00182 
00183     /**
00184      * Destructor. Closes the previously opened library handle.
00185      */
00186     ~data()
00187     {
00188         assert( dlclose( m_dl ) == 0 );
00189     }
00190 
00191     /**
00192      * Constructor. Opens and loads the library.
00193      *
00194      * \see WSharedLib::WSharedLib for details.
00195      *
00196      * \param path the lib to open
00197      */
00198     explicit data( const std::string& path )
00199         : m_path( path ), m_dl( 0 )
00200     {
00201         auto_lock lock;
00202         m_dl = dlopen( m_path.c_str(), RTLD_LAZY );
00203         if( !m_dl )
00204         {
00205             throw WLibraryLoadFailed( std::string( "Could not load library \"" + m_path + "\" due to the error: " + dlerror() ) );
00206         }
00207     }
00208 
00209     /**
00210      * Searches the lib for the specified function symbol and returns it.
00211      *
00212      * \param name the name of the function
00213      *
00214      * \return the pointer to the requested function
00215      *
00216      * \throw WLibraryFetchFailed thrown if the symbol could not be found.
00217      */
00218     func_ptr_type findFunction( const std::string& name )
00219     {
00220         // This cast is supposed to throw a warning because the cast
00221         // of void* to function pointers is not defined or required
00222         // in ISO C. Nevertheless, it works on most current compilers.
00223         //
00224         // man dlsym talks about introducing a new function to circumvent
00225         // this problem.
00226         return reinterpret_cast< func_ptr_type >( findVariable( name ) );
00227     }
00228 
00229     /**
00230      * Searches the lib for the specified symbol and returns it.
00231      *
00232      * \param name the name of the symbol to search.
00233      * \param suppressThrow set to true to suppress the exception. NULL is returned if the symbol does not exists
00234      *
00235      * \return pointer to the symbol.
00236      *
00237      * \throw WLibraryFetchFailed thrown if the symbol could not be found.
00238      *
00239      */
00240     void* findVariable( const std::string& name, bool suppressThrow = false )
00241     {
00242         auto_lock lock;
00243         dlerror();
00244         void* variable_ptr = dlsym( m_dl, name.c_str() );
00245         const char *err = dlerror();
00246         if( !suppressThrow && err )
00247         {
00248             throw WLibraryFetchFailed( std::string( "Could not fetch symbol \"" + name + "\"" + " due to the error: " + err ) );
00249         }
00250         return variable_ptr;
00251     }
00252 
00253     /**
00254      * Check for existence of a given function pointer symbol.
00255      *
00256      * \param name the symbol
00257      *
00258      * \return true if it exists.
00259      */
00260     bool existsFunction( const std::string& name )
00261     {
00262         return findVariable( name, true );
00263     }
00264 };
00265 #endif
00266 
00267 WSharedLib::WSharedLib( boost::filesystem::path lib ):
00268     m_data( new data( lib.string() ) ),
00269     m_libPath( lib )
00270 {
00271 }
00272 
00273 WSharedLib::WSharedLib( const WSharedLib& rhs ):
00274     m_data( new data( rhs.m_data->m_path ) ),
00275     m_libPath( rhs.m_libPath )
00276 {
00277 }
00278 
00279 WSharedLib::~WSharedLib()
00280 {
00281     delete m_data;
00282 }
00283 
00284 WSharedLib& WSharedLib::operator=( const WSharedLib& rhs )
00285 {
00286     WSharedLib o( rhs );
00287     swap( *this, o );
00288     return *this;
00289 }
00290 
00291 void swap( WSharedLib& lhs, WSharedLib& rhs )
00292 {
00293     std::swap( lhs.m_data, rhs.m_data );
00294 }
00295 
00296 WSharedLib::func_ptr_type WSharedLib::findFunction( const std::string& name ) const
00297 {
00298     return m_data->findFunction( name );
00299 }
00300 
00301 void* WSharedLib::findVariable( const std::string& name ) const
00302 {
00303     return m_data->findVariable( name );
00304 }
00305 
00306 bool WSharedLib::existsFunction( const std::string& name ) const
00307 {
00308     return m_data->existsFunction( name );
00309 }
00310 
00311 std::string WSharedLib::getSystemPrefix()
00312 {
00313     return W_LIB_PREFIX;
00314 }
00315 
00316 std::string WSharedLib::getSystemSuffix()
00317 {
00318     return W_LIB_SUFFIX;
00319 }
00320 
00321 std::string WSharedLib::getSystemLibPath()
00322 {
00323     return "../lib";
00324 }
00325 
00326 std::string WSharedLib::getLibraryName()
00327 {
00328     // we want to strip the search directory from the path
00329     std::string relPath( m_libPath.filename().string() );
00330     return relPath;
00331 }
00332