All Classes Namespaces Functions Variables Typedefs Enumerations
shared_library.h
1 /*
2  * Author: Markus Friedrich
3  *
4  * This file is free and unencumbered software released into the public domain.
5  *
6  * Anyone is free to copy, modify, publish, use, compile, sell, or
7  * distribute this software, either in source code form or as a compiled
8  * binary, for any purpose, commercial or non-commercial, and by any
9  * means.
10  *
11  * In jurisdictions that recognize copyright laws, the author or authors
12  * of this software dedicate any and all copyright interest in the
13  * software to the public domain. We make this dedication for the benefit
14  * of the public at large and to the detriment of our heirs and
15  * successors. We intend this dedication to be an overt act of
16  * relinquishment in perpetuity of all present and future rights to this
17  * software under copyright law.
18  *
19  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
20  * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
21  * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
22  * IN NO EVENT SHALL THE AUTHORS BE LIABLE FOR ANY CLAIM, DAMAGES OR
23  * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
24  * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
25  * OTHER DEALINGS IN THE SOFTWARE.
26  *
27  * For more information, please refer to <http://unlicense.org/>
28  */
29 
30 #ifndef _MBXMLUTILS_SHAREDLIBRARY_H_
31 #define _MBXMLUTILS_SHAREDLIBRARY_H_
32 
33 #include <string>
34 #include <map>
35 #include <stdexcept>
36 #include <algorithm>
37 #ifdef _WIN32
38 # include <windows.h>
39 #else
40 # include <dlfcn.h>
41 #endif
42 
43 namespace {
44 
45 inline std::string getLastError() {
46 #ifndef _WIN32
47  const char *err=dlerror();
48  return err?err:"";
49 #else
50  return std::to_string(GetLastError());
51 #endif
52 }
53 
54 }
55 
56 namespace MBXMLUtils {
57 namespace SharedLibrary {
58 
59 #ifndef _WIN32
60  typedef void* Handle;
61 #else
62  typedef HMODULE Handle;
63 #endif
64 
65  typedef int (*InitFuncType)();
66 
67  template<typename T>
68  inline T getSymbol(const std::string &file, const std::string &symbolName, bool throwOnError=true);
69 
70 // Load the libary file, if not already loaded.
71 // Unloads the library only at program exit!!!
72 // file should be a canonical path.
73 Handle load(const std::string &file, bool global=false) {
74  static std::map<std::string, Handle> library;
75  std::pair<std::map<std::string, Handle>::iterator, bool> res=library.insert(std::pair<std::string, Handle>(file, NULL));
76  if(res.second) {
77 #ifndef _WIN32
78  res.first->second=dlopen(file.c_str(), RTLD_NOW | (global ? RTLD_GLOBAL : RTLD_LOCAL) | RTLD_DEEPBIND | RTLD_NODELETE);
79 #else
80  std::string fileWinSep=file;
81  std::replace(fileWinSep.begin(), fileWinSep.end(), '/', '\\'); // LoadLibraryEx can not handle '/' as path separator
82  res.first->second=LoadLibraryEx(fileWinSep.c_str(), NULL, LOAD_WITH_ALTERED_SEARCH_PATH);
83 #endif
84  if(!res.first->second)
85  throw std::runtime_error("Unable to load the library '"+file+"': "+getLastError());
86 
87  // call the init function if it exists
88  InitFuncType initFunc=getSymbol<InitFuncType>(file, "MBXMLUtils_SharedLibrary_init", false);
89  if(initFunc) {
90  int ret=initFunc();
91  if(ret)
92  throw std::runtime_error("Unable to initialize the library '"+file+"'.\n"
93  "The function 'MBXMLUtils_SharedLibrary_init' returned with error code "+std::to_string(ret)+".");
94  }
95  }
96  return res.first->second;
97 }
98 
99 // Load the libary file, if not already loaded and return the symbol symbolName.
100 // Unloads the library only at program exit!!!
101 template<typename T>
102 inline T getSymbol(const std::string &file, const std::string &symbolName, bool throwOnError) {
103  Handle h=load(file);
104 #ifndef _WIN32
105  void *addr=dlsym(h, symbolName.c_str());
106 #else
107  void *addr=reinterpret_cast<void*>(GetProcAddress(h, symbolName.c_str()));
108 #endif
109  if(!addr) {
110  if(throwOnError)
111  throw std::runtime_error("Unable to load the symbol '"+symbolName+"' from library '"+
112  file+"': "+getLastError());
113  else
114  return nullptr;
115  }
116  return reinterpret_cast<T>(reinterpret_cast<size_t>(addr));
117 }
118 
119 }
120 }
121 
122 #endif

Impressum / Disclaimer / Datenschutz Generated by doxygen 1.8.5 Valid HTML