NAMD
dlloader.h
Go to the documentation of this file.
1 #ifndef DLLOADER_H
2 #define DLLOADER_H
3 
4 #include <memory>
5 #include <stdexcept>
6 #include <string>
7 
8 #if defined(WIN32) && !defined(__CYGWIN__)
9 #include "windows.h"
10 #else
11 #include <dlfcn.h>
12 #endif
13 
14 // fix MacOS missing RTLD_DEEPBIND flag in dlopen
15 #if defined(__APPLE__)
16 #undef RTLD_DEEPBIND
17 #define RTLD_DEEPBIND 0
18 #endif
19 
20 namespace dlloader {
21  template <typename T>
23  public:
24  virtual ~DLLoaderInterface() = default;
25  virtual void DLOpenLib() = 0;
26  virtual std::shared_ptr<T> DLGetInstance() = 0;
27  virtual void DLCloseLib() = 0;
28  virtual std::string LibName() const = 0;
29  };
30 #if defined (WIN32)
31  template <typename T>
32  class DLLoader: public DLLoaderInterface<T> {
33  private:
34  HMODULE mHandle;
35  std::string mPathToLib;
36  std::string mAllocClassSymbol;
37  std::string mDeleteClassSymbol;
38  public:
39  DLLoader(
40  std::string pathToLib,
41  std::string allocClassSymbol = "allocator",
42  std::string deleteClassSymbol = "deleter"):
43  mPathToLib(std::move(pathToLib)),
44  mAllocClassSymbol(std::move(allocClassSymbol)),
45  mDeleteClassSymbol(std::move(deleteClassSymbol)) {}
46  ~DLLoader() = default;
47  void DLOpenLib() override {
48  if (!(mHandle = LoadLibrary(mPathToLib.c_str()))) {
49  throw std::runtime_error(std::string{"Cannot open and load "} + mPathToLib);
50  }
51  }
52  void DLCloseLib() override {
53  if (FreeLibrary(mHandle) == 0) {
54  throw std::runtime_error(std::string{"Cannot close "} + mPathToLib);
55  }
56  }
57  std::shared_ptr<T> DLGetInstance() override {
58  using allocClass = T *(*)();
59  using deleteClass = void (*)(T *);
60  auto allocFunc = reinterpret_cast<allocClass>(GetProcAddress(mHandle, mAllocClassSymbol.c_str()));
61  auto deleteFunc = reinterpret_cast<deleteClass>(GetProcAddress(mHandle, mDeleteClassSymbol.c_str()));
62  if (!allocFunc || !deleteFunc) {
63  try {
64  DLCloseLib();
65  } catch (...) {
66  throw;
67  }
68  throw std::runtime_error(std::string{"Cannot find allocator or deleter symbol in "} + mPathToLib);
69  }
70  return std::shared_ptr<T>(allocFunc(), [deleteFunc](T* p){deleteFunc(p);});
71  }
72  std::string LibName() const override {
73  return mPathToLib;
74  }
75  };
76 #else
77  template <typename T>
78  class DLLoader: public DLLoaderInterface<T> {
79  private:
80  void* mHandle;
81  std::string mPathToLib;
82  std::string mAllocClassSymbol;
83  std::string mDeleteClassSymbol;
84  public:
86  std::string pathToLib,
87  std::string allocClassSymbol = "allocator",
88  std::string deleteClassSymbol = "deleter"):
89  mPathToLib(std::move(pathToLib)),
90  mAllocClassSymbol(std::move(allocClassSymbol)),
91  mDeleteClassSymbol(std::move(deleteClassSymbol)) {}
92  ~DLLoader() = default;
93  void DLOpenLib() override {
94  if (!(mHandle = dlopen(mPathToLib.c_str(), RTLD_NOW|RTLD_LAZY|RTLD_DEEPBIND))) {
95  throw std::runtime_error(std::string{dlerror()});
96  }
97  }
98  void DLCloseLib() override {
99  if (dlclose(mHandle) != 0) {
100  throw std::runtime_error(std::string{dlerror()});
101  }
102  }
103  std::shared_ptr<T> DLGetInstance() override {
104  using allocClass = T *(*)();
105  using deleteClass = void (*)(T *);
106  auto allocFunc = reinterpret_cast<allocClass>(dlsym(mHandle, mAllocClassSymbol.c_str()));
107  auto deleteFunc = reinterpret_cast<deleteClass>(dlsym(mHandle, mDeleteClassSymbol.c_str()));
108  if (!allocFunc || !deleteFunc) {
109  try {
110  DLCloseLib();
111  throw std::runtime_error(std::string{dlerror()});
112  } catch (...) {
113  throw;
114  }
115  throw std::runtime_error(std::string{dlerror()});
116  }
117  return std::shared_ptr<T>(allocFunc(), [deleteFunc](T* p){deleteFunc(p);});
118  }
119  std::string LibName() const override {
120  return mPathToLib;
121  }
122  };
123 #endif
124 }
125 
126 #endif // DLLOADER_H
std::string LibName() const override
Definition: dlloader.h:119
virtual void DLCloseLib()=0
DLLoader(std::string pathToLib, std::string allocClassSymbol="allocator", std::string deleteClassSymbol="deleter")
Definition: dlloader.h:85
std::shared_ptr< T > DLGetInstance() override
Definition: dlloader.h:103
virtual ~DLLoaderInterface()=default
void DLCloseLib() override
Definition: dlloader.h:98
virtual std::shared_ptr< T > DLGetInstance()=0
virtual std::string LibName() const =0
void DLOpenLib() override
Definition: dlloader.h:93
virtual void DLOpenLib()=0