--- /dev/null
+////////////////////////////////////////////////////////////////////////////////\r
+\r
+// Author: Andy Rushton\r
+// Copyright: (c) Southampton University 1999-2004\r
+// (c) Andy Rushton 2004-2009\r
+// License: BSD License, see ../docs/license.html\r
+\r
+////////////////////////////////////////////////////////////////////////////////\r
+#include "dynaload.hpp"\r
+\r
+#ifdef MSWINDOWS\r
+#include <windows.h>\r
+#else\r
+#include <dlfcn.h>\r
+#endif\r
+\r
+////////////////////////////////////////////////////////////////////////////////\r
+\r
+#ifdef MSWINDOWS\r
+\r
+static std::string last_error(void)\r
+{\r
+ // get the last error code - if none, return the empty string\r
+ DWORD err = GetLastError();\r
+ if (err == 0) return std::string();\r
+ // get the system message for this error code\r
+ char* message;\r
+ FormatMessage(FORMAT_MESSAGE_ALLOCATE_BUFFER|FORMAT_MESSAGE_FROM_SYSTEM|FORMAT_MESSAGE_IGNORE_INSERTS,\r
+ 0,\r
+ err,\r
+ MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT),\r
+ (LPTSTR)&message,\r
+ 0,0);\r
+ std::string result = message;\r
+ LocalFree(message);\r
+ // the error message is for some perverse reason newline terminated - remove this\r
+ if (result[result.size()-1] == '\n')\r
+ result.erase(result.end()-1);\r
+ if (result[result.size()-1] == '\r')\r
+ result.erase(result.end()-1);\r
+ return result;\r
+}\r
+\r
+#else\r
+\r
+static std::string last_error(void)\r
+{\r
+ return std::string(dlerror());\r
+}\r
+\r
+#endif\r
+\r
+////////////////////////////////////////////////////////////////////////////////\r
+\r
+namespace stlplus\r
+{\r
+\r
+ ////////////////////////////////////////////////////////////////////////////////\r
+ // library management\r
+\r
+ // construct the object but do not load\r
+ dynaload::dynaload(void) : m_handle(0) \r
+ {\r
+ }\r
+\r
+ // construct and load\r
+ dynaload::dynaload(const std::string& library) : m_handle(0)\r
+ {\r
+ load(library);\r
+ }\r
+\r
+ // destroy and unload if loaded\r
+ dynaload::~dynaload(void)\r
+ {\r
+ unload();\r
+ }\r
+\r
+ // load the library - return success or fail\r
+ bool dynaload::load(const std::string& library)\r
+ {\r
+#ifdef MSWINDOWS\r
+ m_handle = (void*)LoadLibrary(library.c_str());\r
+#elif defined(CYGWIN)\r
+ m_handle = dlopen(library.c_str(),RTLD_NOW);\r
+#else\r
+ std::string full_library = std::string("lib") + library + std::string(".so");\r
+ m_handle = dlopen(full_library.c_str(),RTLD_NOW);\r
+#endif\r
+ if (!m_handle)\r
+ {\r
+ m_error = load_error;\r
+ m_text = last_error();\r
+ }\r
+ return loaded();\r
+ }\r
+\r
+ // unload the library if loaded\r
+ bool dynaload::unload(void)\r
+ {\r
+ if (!loaded()) return false;\r
+#ifdef MSWINDOWS\r
+ int status = FreeLibrary((HINSTANCE)m_handle) ? 0 : 1;\r
+#else\r
+ int status = dlclose(m_handle);\r
+#endif\r
+ if (status != 0)\r
+ {\r
+ m_error = unload_error;\r
+ m_text = last_error();\r
+ }\r
+ return status == 0;\r
+ }\r
+\r
+ // test whether the library is loaded\r
+ bool dynaload::loaded(void) const\r
+ {\r
+ return m_handle != 0;\r
+ }\r
+\r
+ ////////////////////////////////////////////////////////////////////////////\r
+ // symbol management\r
+\r
+ // test whether a function is exported by the library\r
+ // does not set the error flag if fails\r
+ bool dynaload::present(const std::string& name)\r
+ {\r
+ if (!loaded()) return false;\r
+#ifdef MSWINDOWS\r
+ void* fn = (void*)GetProcAddress((HINSTANCE)m_handle,name.c_str());\r
+#else\r
+ void* fn = dlsym(m_handle,name.c_str());\r
+#endif\r
+ return fn != 0;\r
+ }\r
+\r
+ // get the function as a generic pointer\r
+ void* dynaload::symbol(const std::string& name)\r
+ {\r
+ if (!loaded()) return 0;\r
+#ifdef MSWINDOWS\r
+ void* fn = (void*)GetProcAddress((HINSTANCE)m_handle,name.c_str());\r
+#else\r
+ void* fn = dlsym(m_handle,name.c_str());\r
+#endif\r
+ if (!fn)\r
+ {\r
+ m_error = symbol_error;\r
+ m_text = last_error();\r
+ }\r
+ return fn;\r
+ }\r
+\r
+ ////////////////////////////////////////////////////////////////////////////\r
+ // error management\r
+\r
+ // test whether there has been an error\r
+ bool dynaload::error(void) const\r
+ {\r
+ return m_error != no_error;\r
+ }\r
+\r
+ // clear an error once it has been handled (or ignored)\r
+ void dynaload::clear_error(void)\r
+ {\r
+ m_error = no_error;\r
+ m_text = std::string();\r
+ }\r
+\r
+ // get the type of the error as indicated by the enum error_t\r
+ dynaload::error_t dynaload::error_type(void) const\r
+ {\r
+ return m_error;\r
+ }\r
+\r
+ // get the text of the error as provided by the OS\r
+ std::string dynaload::error_text(void) const\r
+ {\r
+ return m_text;\r
+ }\r
+\r
+\r
+////////////////////////////////////////////////////////////////////////////////\r
+\r
+} // end namespace stlplus\r