gfactory
gdl.h
Go to the documentation of this file.
1 #pragma once
2 
3 // geomc
4 #include "glogger.h"
5 #include "gutilities.h"
6 
7 // c++ plugin loading functions
8 // documentation: http://www.faqs.org/docs/Linux-mini/C++-dlopen.html
9 #include <dlfcn.h>
10 
11 // c++
12 #include <sys/stat.h> // to check if file exists
13 #include <string>
14 
15 typedef void* dlhandle;
16 
17 static dlhandle load_lib(const std::string& path);
18 
19 static void close_lib(dlhandle handle);
20 
21 // exit codes: 1000s
22 #define ERR_DLNOTFOUND 1001
23 #define ERR_FACTORYNOTFOUND 1002
24 #define ERR_DLHANDLENOTFOUND 1003
25 
26 
31 struct DynamicLib {
32 
33 private:
34  std::string dlFileName; // dynamic library file
35 
36  bool doesFileExists(const std::string& name) {
37  struct stat buffer{};
38  return (stat(name.c_str(), &buffer) == 0);
39  }
40 
41  std::shared_ptr<GLogger> log;
42 
43 public:
44  // default constructor
45  DynamicLib() = default;
46 
47  // path here is the filename
48  DynamicLib(std::shared_ptr<GLogger> logger, std::string path) : dlFileName(path), log(logger), handle(nullptr) {
49  log->debug(CONSTRUCTOR, "Instantiating ", path);
50  log->debug(NORMAL, "Trying ", dlFileName);
51 
52  // trying installation path + lib if not found
53  if (!doesFileExists(dlFileName)) {
54  log->debug(NORMAL, dlFileName, " not found...");
55 
56  std::filesystem::path gemcRoot = gutilities::gemc_root();
57  dlFileName = gemcRoot.string() + "/lib/" + path;
58 
59  log->debug(NORMAL, "Trying ", dlFileName);
60  }
61 
62  if (doesFileExists(dlFileName)) {
63  handle = load_lib(dlFileName);
64  if (handle == nullptr) {
65  char const* const dlopen_error = dlerror();
66  log->error(ERR_DLHANDLENOTFOUND, "File ", dlFileName, " found, but handle is null. Error: ",
67  dlopen_error);
68  }
69  else { log->info(0, "Loaded ", dlFileName); }
70  }
71  else { log->error(ERR_DLNOTFOUND, "could not find ", dlFileName); }
72  }
73 
74  dlhandle handle = nullptr; // posix handle of the dynamic library
75 
77  if (handle != nullptr) {
78  close_lib(handle);
79  log->debug(DESTRUCTOR, "Destroying ", dlFileName);
80  }
81  }
82 
83 
84 };
85 
86 
87 dlhandle load_lib(const std::string& lib) // never throws
88 {
89  dlhandle h = nullptr;
90 
91  // If the caller already supplied a path (has a slash) just try it.
92  if (lib.find('/') != std::string::npos) { h = dlopen(lib.c_str(), RTLD_NOW); }
93  else {
94  // 1. Try the file in the current working directory
95  std::string cwdPath = "./" + lib;
96  h = dlopen(cwdPath.c_str(), RTLD_NOW);
97 
98  // 2. Fallback to the normal search path so LD_LIBRARY_PATH,
99  // RPATH/RUNPATH, system dirs, etc. are still honoured.
100  if (!h) { h = dlopen(lib.c_str(), RTLD_NOW); }
101  }
102  return h; // may be nullptr – caller should check and use dlerror()
103 }
104 
105 static void close_lib(dlhandle handle) { dlclose(handle); }
void * dlhandle
Definition: gdl.h:15
#define ERR_DLNOTFOUND
Definition: gdl.h:22
#define ERR_DLHANDLENOTFOUND
Definition: gdl.h:24
Structure to load dynamically symbols from a shared library.
Definition: gdl.h:31
DynamicLib(std::shared_ptr< GLogger > logger, std::string path)
Definition: gdl.h:48
dlhandle handle
Definition: gdl.h:74
~DynamicLib()
Definition: gdl.h:76
DynamicLib()=default