libmoost
|
00001 #include <dlfcn.h> 00002 #include <errno.h> 00003 #include <cstring> 00004 00005 #include <boost/filesystem/path.hpp> 00006 00007 namespace moost { namespace pdl { 00008 00009 class dynamic_library_impl : public dynamic_library_if 00010 { 00011 public: 00012 dynamic_library_impl(const std::string& library_name, bool resolve_symbols); 00013 00014 ~dynamic_library_impl(); 00015 00016 void *get_symbol_by_name(const std::string& symbol_name) const; 00017 00018 const std::string& library_path() const 00019 { 00020 return m_library_path; 00021 } 00022 00023 private: 00024 typedef void * library_handle_t; 00025 00026 static library_handle_t open_library(const std::string& library_name, bool resolve_symbols); 00027 static const char *default_suffix(); 00028 std::string get_last_error() const; 00029 bool is_file_not_found_error(const std::string& error) const; 00030 00031 std::string m_library_path; 00032 library_handle_t m_library; 00033 }; 00034 00035 dynamic_library_impl::dynamic_library_impl(const std::string& library_name, bool resolve_symbols) 00036 { 00037 std::string lib_path(library_name); 00038 std::string error; 00039 00040 m_library = open_library(lib_path, resolve_symbols); 00041 00042 if (!m_library) 00043 { 00044 error = get_last_error(); 00045 00046 if (is_file_not_found_error(error)) 00047 { 00048 lib_path += default_suffix(); 00049 00050 m_library = open_library(lib_path, resolve_symbols); 00051 00052 if (!m_library) 00053 { 00054 error = get_last_error(); 00055 00056 if (is_file_not_found_error(error)) 00057 { 00058 boost::filesystem::path path(lib_path); 00059 lib_path = (path.parent_path()/("lib" + path.filename())).string(); 00060 00061 m_library = open_library(lib_path, resolve_symbols); 00062 00063 if (!m_library) 00064 { 00065 error = get_last_error(); 00066 } 00067 } 00068 } 00069 } 00070 } 00071 00072 if (!m_library) 00073 { 00074 if (is_file_not_found_error(error)) 00075 { 00076 throw library_not_found_error(error); 00077 } 00078 else 00079 { 00080 throw library_load_error(error); 00081 } 00082 } 00083 00084 m_library_path = lib_path; 00085 } 00086 00087 bool dynamic_library_impl::is_file_not_found_error(const std::string& error) const 00088 { 00089 char buf[128] = {'\0'}; 00090 const char *enoent = &buf[0]; 00091 00092 #if (_POSIX_C_SOURCE >= 200112L || _XOPEN_SOURCE >= 600) && ! _GNU_SOURCE 00093 strerror_r(ENOENT, buf, sizeof(buf)); 00094 #else 00095 enoent = strerror_r(ENOENT, buf, sizeof(buf)); 00096 #endif 00097 00098 return error.rfind(enoent) != std::string::npos; 00099 } 00100 00101 dynamic_library_impl::~dynamic_library_impl() 00102 { 00103 try 00104 { 00105 dlclose(m_library); 00106 } 00107 catch (...) 00108 { 00109 // there's nothing we can do here 00110 } 00111 } 00112 00113 dynamic_library_impl::library_handle_t dynamic_library_impl::open_library(const std::string& library_name, bool resolve_symbols) 00114 { 00115 return dlopen(library_name.c_str(), RTLD_LOCAL | (resolve_symbols ? RTLD_NOW : RTLD_LAZY)); 00116 } 00117 00118 const char *dynamic_library_impl::default_suffix() 00119 { 00120 #if defined(hpux) || defined(_hpux) || defined(__hpux) 00121 return ".sl"; 00122 #else 00123 return ".so"; 00124 #endif 00125 } 00126 00127 void *dynamic_library_impl::get_symbol_by_name(const std::string& symbol_name) const 00128 { 00129 return dlsym(m_library, symbol_name.c_str()); 00130 } 00131 00132 std::string dynamic_library_impl::get_last_error() const 00133 { 00134 try 00135 { 00136 return std::string(dlerror()); 00137 } 00138 catch (...) 00139 { 00140 return std::string("unknown error"); 00141 } 00142 } 00143 00144 }}