OpenWalnut  1.5.0dev
WSharedLib.cpp
1 //---------------------------------------------------------------------------
2 //
3 // Project: OpenWalnut ( http://www.openwalnut.org )
4 //
5 // Copyright 2009 OpenWalnut Community, BSV@Uni-Leipzig and CNCF@MPI-CBS
6 // For more information see http://www.openwalnut.org/copying
7 //
8 // This file is part of OpenWalnut.
9 //
10 // OpenWalnut is free software: you can redistribute it and/or modify
11 // it under the terms of the GNU Lesser General Public License as published by
12 // the Free Software Foundation, either version 3 of the License, or
13 // (at your option) any later version.
14 //
15 // OpenWalnut is distributed in the hope that it will be useful,
16 // but WITHOUT ANY WARRANTY; without even the implied warranty of
17 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
18 // GNU Lesser General Public License for more details.
19 //
20 // You should have received a copy of the GNU Lesser General Public License
21 // along with OpenWalnut. If not, see <http://www.gnu.org/licenses/>.
22 //
23 //---------------------------------------------------------------------------
24 
25 #include <algorithm>
26 #include <cassert>
27 #include <string>
28 
29 #ifdef _WIN32
30  #include <iostream>
31  #include <windows.h> // NOLINT
32 #endif
33 
34 #include <boost/filesystem.hpp>
35 
36 #include "exceptions/WLibraryFetchFailed.h"
37 #include "exceptions/WLibraryLoadFailed.h"
38 #include "WSharedLib.h"
39 
40 #ifdef _WIN32
41 
42 /**
43  * Simple class holding an opened library.
44  */
45 struct WSharedLib::data
46 {
47  /**
48  * Path of lib.
49  */
50  const std::string m_path;
51 
52  /**
53  * Handle describing the loaded lib.
54  */
55  HMODULE m_hDLL;
56 
57  /**
58  * Constructor. Opens and loads the library.
59  *
60  * \see WSharedLib::WSharedLib for details.
61  *
62  * \param path the lib to open
63  */
64  explicit data( const std::string& path ):
65  m_path( path ),
66  m_hDLL( LoadLibrary( path.c_str() ) )
67  {
68  if( !m_hDLL )
69  {
70  throw WLibraryLoadFailed( std::string( "Could not load library \"" + m_path + "\" due to the error: " + errmsg() ) );
71  }
72  }
73 
74  /**
75  * Destructor. Closes the previously opened library handle.
76  */
77  ~data()
78  {
79  FreeLibrary( m_hDLL );
80  }
81 
82  /**
83  * Searches the lib for the specified function symbol and returns it.
84  *
85  * \param name the name of the function
86  *
87  * \return the pointer to the requested function
88  *
89  * \throw WLibraryFetchFailed thrown if the symbol could not be found.
90  */
91  func_ptr_type findFunction( const std::string& name )
92  {
93  func_ptr_type func_ptr = reinterpret_cast< func_ptr_type >( GetProcAddress( m_hDLL, name.c_str() ) );
94  if( !func_ptr )
95  {
96  throw WLibraryFetchFailed( std::string( "Could not fetch symbol \"" + name + "\"" + " due to the error: " + errmsg() ) );
97  }
98  return func_ptr;
99  }
100 
101  /**
102  * Check for existence of a given function pointer symbol.
103  *
104  * \param name the symbol
105  *
106  * \return true if it exists.
107  */
108  bool existsFunction( const std::string& name )
109  {
110  func_ptr_type func_ptr = reinterpret_cast< func_ptr_type >( GetProcAddress( m_hDLL, name.c_str() ) );
111  return func_ptr;
112  }
113 
114  /**
115  * Searches the lib for the specified function symbol and returns it.
116  *
117  * \param name the name of the function
118  *
119  * \return the pointer to the requested function
120  *
121  * \throw WLibraryFetchFailed thrown if the symbol could not be found.
122  */
123  void* findVariable( const std::string& name )
124  {
125  return reinterpret_cast< void* >( findFunction( name ) );
126  }
127 
128  /**
129  * Constructs a nice looking error message for the last error occurred.
130  *
131  * \return the last error message
132  */
133  static std::string errmsg()
134  {
135  std::string msg;
136  LPTSTR lpMsgBuf = 0;
137  FormatMessage( FORMAT_MESSAGE_ALLOCATE_BUFFER | FORMAT_MESSAGE_FROM_SYSTEM | FORMAT_MESSAGE_IGNORE_INSERTS, 0, GetLastError(), 0,
138  reinterpret_cast< LPTSTR >( &lpMsgBuf ), 0, 0 );
139  LPTSTR p = lpMsgBuf;
140  while( *p )
141  {
142  msg.push_back( *p++ );
143  }
144  LocalFree( lpMsgBuf );
145  return msg;
146  }
147 };
148 #else
149 #include <dlfcn.h> // NOLINT
150 #include <pthread.h> // NOLINT
151 
152 namespace
153 {
154  pthread_mutex_t mutex = PTHREAD_MUTEX_INITIALIZER;
155  struct auto_lock
156  {
157  auto_lock()
158  {
159  pthread_mutex_lock( &mutex );
160  }
161  ~auto_lock()
162  {
163  pthread_mutex_unlock( &mutex );
164  }
165  };
166 }
167 
168 /**
169  * Simple class holding an opened library.
170  */
172 {
173  /**
174  * Path of lib.
175  */
176  const std::string m_path;
177 
178  /**
179  * Handle describing the loaded lib.
180  */
181  void* m_dl;
182 
183  /**
184  * Destructor. Closes the previously opened library handle.
185  */
187  {
188  assert( dlclose( m_dl ) == 0 );
189  }
190 
191  /**
192  * Constructor. Opens and loads the library.
193  *
194  * \see WSharedLib::WSharedLib for details.
195  *
196  * \param path the lib to open
197  */
198  explicit data( const std::string& path )
199  : m_path( path ), m_dl( 0 )
200  {
201  auto_lock lock;
202  m_dl = dlopen( m_path.c_str(), RTLD_LAZY );
203  if( !m_dl )
204  {
205  throw WLibraryLoadFailed( std::string( "Could not load library \"" + m_path + "\" due to the error: " + dlerror() ) );
206  }
207  }
208 
209  /**
210  * Searches the lib for the specified function symbol and returns it.
211  *
212  * \param name the name of the function
213  *
214  * \return the pointer to the requested function
215  *
216  * \throw WLibraryFetchFailed thrown if the symbol could not be found.
217  */
218  func_ptr_type findFunction( const std::string& name )
219  {
220  // This cast is supposed to throw a warning because the cast
221  // of void* to function pointers is not defined or required
222  // in ISO C. Nevertheless, it works on most current compilers.
223  //
224  // man dlsym talks about introducing a new function to circumvent
225  // this problem.
226  return reinterpret_cast< func_ptr_type >( findVariable( name ) );
227  }
228 
229  /**
230  * Searches the lib for the specified symbol and returns it.
231  *
232  * \param name the name of the symbol to search.
233  * \param suppressThrow set to true to suppress the exception. NULL is returned if the symbol does not exists
234  *
235  * \return pointer to the symbol.
236  *
237  * \throw WLibraryFetchFailed thrown if the symbol could not be found.
238  *
239  */
240  void* findVariable( const std::string& name, bool suppressThrow = false )
241  {
242  auto_lock lock;
243  dlerror();
244  void* variable_ptr = dlsym( m_dl, name.c_str() );
245  const char *err = dlerror();
246  if( !suppressThrow && err )
247  {
248  throw WLibraryFetchFailed( std::string( "Could not fetch symbol \"" + name + "\"" + " due to the error: " + err ) );
249  }
250  return variable_ptr;
251  }
252 
253  /**
254  * Check for existence of a given function pointer symbol.
255  *
256  * \param name the symbol
257  *
258  * \return true if it exists.
259  */
260  bool existsFunction( const std::string& name )
261  {
262  return findVariable( name, true );
263  }
264 };
265 #endif
266 
267 WSharedLib::WSharedLib( boost::filesystem::path lib ):
268  m_data( new data( lib.string() ) ),
269  m_libPath( lib )
270 {
271 }
272 
274  m_data( new data( rhs.m_data->m_path ) ),
275  m_libPath( rhs.m_libPath )
276 {
277 }
278 
280 {
281  delete m_data;
282 }
283 
285 {
286  WSharedLib o( rhs );
287  swap( *this, o );
288  return *this;
289 }
290 
291 void swap( WSharedLib& lhs, WSharedLib& rhs )
292 {
293  std::swap( lhs.m_data, rhs.m_data );
294 }
295 
296 WSharedLib::func_ptr_type WSharedLib::findFunction( const std::string& name ) const
297 {
298  return m_data->findFunction( name );
299 }
300 
301 void* WSharedLib::findVariable( const std::string& name ) const
302 {
303  return m_data->findVariable( name );
304 }
305 
306 bool WSharedLib::existsFunction( const std::string& name ) const
307 {
308  return m_data->existsFunction( name );
309 }
310 
312 {
313  return W_LIB_PREFIX;
314 }
315 
317 {
318  return W_LIB_SUFFIX;
319 }
320 
322 {
323  return "../lib";
324 }
325 
327 {
328  // we want to strip the search directory from the path
329  std::string relPath( m_libPath.filename().string() );
330  return relPath;
331 }
332 
Thrown whenever a symbol could not be fetched.
Thrown whenever a library could not been loaded.
This class loads shared libraries and provides function pointers.
Definition: WSharedLib.h:45
static std::string getSystemSuffix()
Returns the suffix for libraries used on the system.
Definition: WSharedLib.cpp:316
static std::string getSystemPrefix()
Returns the prefix used for libraries on the system.
Definition: WSharedLib.cpp:311
static std::string getSystemLibPath()
Returns the default path for libraries on the current system.
Definition: WSharedLib.cpp:321
data * m_data
internal data
Definition: WSharedLib.h:176
boost::filesystem::path m_libPath
path to lib
Definition: WSharedLib.h:182
virtual ~WSharedLib()
Destructor.
Definition: WSharedLib.cpp:279
void * findVariable(const std::string &name) const
Find the specified symbol in the library.
Definition: WSharedLib.cpp:301
func_ptr_type findFunction(const std::string &name) const
Find the specified function pointer in the library.
Definition: WSharedLib.cpp:296
friend void swap(WSharedLib &lhs, WSharedLib &rhs)
Swap to shared libraries.
Definition: WSharedLib.cpp:291
bool existsFunction(const std::string &name) const
Check whether the function exists.
Definition: WSharedLib.cpp:306
void(* func_ptr_type)(void)
neutral function pointer type
Definition: WSharedLib.h:155
WSharedLib(boost::filesystem::path lib)
Constructor.
Definition: WSharedLib.cpp:267
std::string getLibraryName()
Returns the filename of the library without path.
Definition: WSharedLib.cpp:326
WSharedLib & operator=(const WSharedLib &rhs)
Copy assignment for shared libraries.
Definition: WSharedLib.cpp:284
Simple class holding an opened library.
Definition: WSharedLib.cpp:172
void * findVariable(const std::string &name, bool suppressThrow=false)
Searches the lib for the specified symbol and returns it.
Definition: WSharedLib.cpp:240
void * m_dl
Handle describing the loaded lib.
Definition: WSharedLib.cpp:181
bool existsFunction(const std::string &name)
Check for existence of a given function pointer symbol.
Definition: WSharedLib.cpp:260
const std::string m_path
Path of lib.
Definition: WSharedLib.cpp:176
~data()
Destructor.
Definition: WSharedLib.cpp:186
data(const std::string &path)
Constructor.
Definition: WSharedLib.cpp:198
func_ptr_type findFunction(const std::string &name)
Searches the lib for the specified function symbol and returns it.
Definition: WSharedLib.cpp:218