libmoost
/home/mhx/git/github/libmoost/src/pdl/impl/dl_posix.ipp
Go to the documentation of this file.
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 }}