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 handle = load_lib(dlFileName);
108 if (handle == nullptr) {
109 char const* const dlopen_error = dlerror();
110 log->error(ERR_DLHANDLENOTFOUND, "File ", dlFileName, " found, but handle is null. dlopen_error >> ",
111 dlopen_error);
112 }
113 else { log->info(0, "Loaded ", dlFileName); }
114 }
115 else { log->error(ERR_DLNOTFOUND, "could not find ", dlFileName); }
116 }
117
123 dlhandle handle = nullptr;
124
131 if (handle != nullptr) {
132 close_lib(handle);
133 log->debug(DESTRUCTOR, "Destroying ", dlFileName);
134 }
135 }
136};
137
138
150dlhandle load_lib(const std::string& lib) // never throws
151{
152 dlhandle h = nullptr;
153
154 // If the caller already supplied a path (has a slash) just try it.
155 if (lib.find('/') != std::string::npos) { h = dlopen(lib.c_str(), RTLD_NOW); }
156 else {
157 // 1. Try the file in the current working directory.
158 std::string cwdPath = "./" + lib;
159 h = dlopen(cwdPath.c_str(), RTLD_NOW);
160
161 // 2. Fallback to the normal search path so LD_LIBRARY_PATH,
162 // RPATH/RUNPATH, system dirs, etc. are still honoured.
163 if (!h) { h = dlopen(lib.c_str(), RTLD_NOW); }
164 }
165 return h; // may be nullptr – caller should check and use dlerror()
166}
167
172static 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:123
~DynamicLib()
Destructor closes the library handle (if loaded).
Definition gdl.h:130
DynamicLib()=default
Default constructor (does not load anything).