changeset 558:5725e2d2ab4c

Dynlib: add overload that does not throw
author David Demelier <markand@malikania.fr>
date Sun, 19 Jun 2016 16:52:32 +0200
parents a8b5e0bb59f7
children 5554ba5dc1dc
files modules/dynlib/dynlib.hpp modules/dynlib/test/main.cpp
diffstat 2 files changed, 29 insertions(+), 22 deletions(-) [+]
line wrap: on
line diff
--- a/modules/dynlib/dynlib.hpp	Sun Jun 19 16:41:10 2016 +0200
+++ b/modules/dynlib/dynlib.hpp	Sun Jun 19 16:52:32 2016 +0200
@@ -118,8 +118,8 @@
  *  try {
  *      Dynlib dso("./plugin" DYNLIB_SUFFIX);
  *
- *      dso.sym<PluginLoad>("plugin_load")();
- *      dso.sym<PluginUnload>("plugin_unload")();
+ *      dso.require<PluginLoad>("plugin_load")();
+ *      dso.require<PluginUnload>("plugin_unload")();
  *  } catch (const std::exception &ex) {
  *      std::cerr << ex.what() << std::endl;
  *  }
@@ -254,15 +254,30 @@
     /**
      * Get a symbol from the library.
      *
-     * On some platforms the symbol must be manually exported.
+     * \param name the symbol
+     * \return the symbol
+     * \throw std::out_of_range on error
+     * \see DYNLIB_EXPORT
+     */
+    template <typename T>
+    inline T require(const std::string &name)
+    {
+        auto sym = get<T>(name);
+
+        if (!sym)
+            throw std::out_of_range(name + ": symbol not found");
+
+        return sym;
+    }
+
+    /**
+     * Get a symbol from the library or return nullptr if not found.
      *
      * \param name the symbol
      * \return the symbol
-     * \throw std::runtime_error on error
-     * \see DYNLIB_EXPORT
      */
     template <typename T>
-    T sym(const std::string &name);
+    T get(const std::string &name) noexcept;
 };
 
 #if defined(_WIN32)
@@ -287,14 +302,9 @@
 }
 
 template <typename T>
-T Dynlib::sym(const std::string &name)
+inline T Dynlib::get(const std::string &name) noexcept
 {
-    Sym sym = GetProcAddress(m_handle, name.c_str());
-
-    if (sym == nullptr)
-        throw std::runtime_error(error());
-
-    return reinterpret_cast<T>(sym);
+    return reinterpret_cast<T>(GetProcAddress(m_handle, name.c_str()));
 }
 
 #else
@@ -319,14 +329,9 @@
 }
 
 template <typename T>
-T Dynlib::sym(const std::string &name)
+inline T Dynlib::get(const std::string &name) noexcept
 {
-    Sym sym = dlsym(m_handle, name.c_str());
-
-    if (sym == nullptr)
-        throw std::runtime_error(dlerror());
-
-    return reinterpret_cast<T>(sym);
+    return reinterpret_cast<T>(dlsym(m_handle, name.c_str()));
 }
 
 #endif
--- a/modules/dynlib/test/main.cpp	Sun Jun 19 16:41:10 2016 +0200
+++ b/modules/dynlib/test/main.cpp	Sun Jun 19 16:52:32 2016 +0200
@@ -28,7 +28,7 @@
 {
     try {
         Dynlib library(PLUGIN);
-        Initialize init = library.sym<Initialize>("initialize");
+        Initialize init = library.require<Initialize>("initialize");
 
         std::string expected("Hello World");
         std::string result;
@@ -36,6 +36,7 @@
         init(result);
 
         ASSERT_EQ(expected, result);
+        ASSERT_TRUE(library.get<Initialize>("initialize"));
     } catch (const std::runtime_error &error) {
         FAIL() << error.what();
     }
@@ -45,7 +46,8 @@
 {
     Dynlib library(PLUGIN);
 
-    ASSERT_THROW(library.sym<Initialize>("initialize_typo"), std::runtime_error);
+    ASSERT_THROW(library.require<Initialize>("initialize_typo"), std::out_of_range);
+    ASSERT_FALSE(library.get<Initialize>("initialize_type"));
 }
 
 int main(int argc, char **argv)