gfactory
Loading...
Searching...
No Matches
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// POSIX dynamic loading
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
19typedef void* dlhandle;
20
21static dlhandle load_lib(const std::string& path);
22static void close_lib(dlhandle handle);
23
24// exit codes: 1000s
25#define ERR_DLNOTFOUND 1001
26#define ERR_FACTORYNOTFOUND 1002
27#define ERR_DLHANDLENOTFOUND 1003
28
29
51{
52private:
54 std::string dlFileName;
55
61 bool doesFileExists(const std::string& name) {
62 struct stat buffer{};
63 return (stat(name.c_str(), &buffer) == 0);
64 }
65
67 std::shared_ptr<GLogger> log;
68
69public:
71 DynamicLib() = default;
72
82 DynamicLib(std::shared_ptr<GLogger> logger, std::string path) : dlFileName(path), log(logger), handle(nullptr) {
83 log->debug(CONSTRUCTOR, "Instantiating ", path);
84 log->debug(NORMAL, "Trying ", dlFileName);
85
86 // Try installation path + "/lib" if not found at the provided location.
87 if (!doesFileExists(dlFileName)) {
88 log->debug(NORMAL, dlFileName, " not found...");
89
90 std::filesystem::path gemcRoot = gutilities::gemc_root();
91 dlFileName = gemcRoot.string() + "/lib/" + path;
92
93 log->debug(NORMAL, "Trying ", dlFileName);
94 }
95
96 // Try installation path + "/build" if not found - allows Meson tests to run from the build dir.
97 if (!doesFileExists(dlFileName)) {
98 log->debug(NORMAL, dlFileName, " not found...");
99
100 std::filesystem::path gemcRoot = gutilities::gemc_root();
101 dlFileName = gemcRoot.string() + "/build/" + path;
102
103 log->debug(NORMAL, "Trying ", dlFileName);
104 }
105
106 if (doesFileExists(dlFileName)) {
107 dlFileName = std::filesystem::absolute(dlFileName).string();
108 handle = load_lib(dlFileName);
109 if (handle == nullptr) {
110 char const* const dlopen_error = dlerror();
111 log->error(ERR_DLHANDLENOTFOUND, "File ", dlFileName, " found, but handle is null. dlopen_error >> ",
112 dlopen_error != nullptr ? dlopen_error : "unknown dlopen error");
113 }
114 else { log->info(1, "Loaded ", dlFileName); }
115 }
116 else { log->error(ERR_DLNOTFOUND, "could not find ", dlFileName); }
117 }
118
124 dlhandle handle = nullptr;
125
132 if (handle != nullptr) {
133 close_lib(handle);
134 log->debug(DESTRUCTOR, "Destroying ", dlFileName);
135 }
136 }
137};
138
139
151dlhandle load_lib(const std::string& lib) // never throws
152{
153 dlhandle h = nullptr;
154
155#if defined(__linux__) && defined(RTLD_NODELETE)
156 constexpr int dlopen_flags = RTLD_NOW | RTLD_NODELETE;
157#else
158 constexpr int dlopen_flags = RTLD_NOW;
159#endif
160
161 // If the caller already supplied a path (has a slash) just try it.
162 if (lib.find('/') != std::string::npos) { h = dlopen(lib.c_str(), dlopen_flags); }
163 else {
164 // 1. Try the file in the current working directory.
165 std::string cwdPath = "./" + lib;
166 h = dlopen(cwdPath.c_str(), dlopen_flags);
167
168 // 2. Fallback to the normal search path so LD_LIBRARY_PATH,
169 // RPATH/RUNPATH, system dirs, etc. are still honoured.
170 if (!h) { h = dlopen(lib.c_str(), dlopen_flags); }
171 }
172 return h; // may be nullptr – caller should check and use dlerror()
173}
174
179static void close_lib(dlhandle handle) { dlclose(handle); }
#define ERR_DLNOTFOUND
Definition gdl.h:25
#define ERR_DLHANDLENOTFOUND
Definition gdl.h:27
void * dlhandle
Opaque handle returned by dlopen and consumed by dlsym / dlclose.
Definition gdl.h:19
CONSTRUCTOR
NORMAL
DESTRUCTOR
std::filesystem::path gemc_root()
Helper that loads a shared library and holds its POSIX handle.
Definition gdl.h:51
DynamicLib(std::shared_ptr< GLogger > logger, std::string path)
Construct and attempt to load a dynamic library.
Definition gdl.h:82
dlhandle handle
POSIX handle of the dynamic library.
Definition gdl.h:124
~DynamicLib()
Destructor closes the library handle (if loaded).
Definition gdl.h:131
DynamicLib()=default
Default constructor (does not load anything).