OpenWalnut 1.3.1
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      * 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