-
Notifications
You must be signed in to change notification settings - Fork 1
/
dlmm.hh
88 lines (72 loc) · 3 KB
/
dlmm.hh
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
#ifndef LIBDLMM_DL_HH
#define LIBDLMM_DL_HH
#include <cassert>
#include <dlfcn.h>
#include <stdexcept>
/** @short Wrapper for POSIX dynamic libraries.
* Link with -ldl */
class Dl {
public:
/** @short Open a dynamic library file.
* @exception std::runtime_error If the library cannot be opened.
* @param filename Library file name.
* @param flags Flags to pass to dlopen(), RTLD_LAZY by default. */
explicit Dl(std::string const &filename, int flags = RTLD_LAZY)
: m_library(dlopen(filename.c_str(), flags)) {
if (m_library == nullptr)
throw std::runtime_error(
std::string("Dl::Dl(\"" + filename + "\"): ") + dlerror());
}
/** @short Close a dynamic library file. */
~Dl() { dlclose(m_library); }
/** @short Get a reference to a symbol in a library.
* @param Name of the symbol to search for.
* @return A reference to given symbol of type T.
* @exception std::runtime_error If the given symbol cannot be found. */
template <typename T> T &symbol(std::string const &symbol_name) const {
// Convert a void pointer to a function pointer without warnings.
// Since we're type punning, make sure that pointer sizes do not differ.
assert(sizeof(void *) == sizeof(void (*)()));
union {
void *m_void;
T *m_real;
} ptr;
ptr.m_void = dlsym(m_library, symbol_name.c_str());
if (ptr.m_void == nullptr)
throw std::runtime_error(
std::string("Dl::symbol(\"" + symbol_name + "\"): ") +
dlerror());
return *ptr.m_real;
}
#ifdef _GNU_SOURCE // GNU extensions
// Dlvsym() is supported through function overloading.
/** @short Get a pointer to a symbol of certain version in a library.
* @param symbol_name Name of the symbol to search for.
* @param version Version of the symbol to search for.
* @return A pointer to given symbol of type T.
* @exception std::runtime_error If the given symbol cannot be found. */
template <typename T>
T &symbol(std::string const &symbol_name,
std::string const &version) const {
// Convert a void pointer to a function pointer without warnings.
// Since we're type punning, make sure that pointer sizes do not differ.
assert(sizeof(void *) == sizeof(void (*)()));
union {
void *m_void;
T *m_real;
} ptr;
ptr.m_void = dlvsym(m_library, symbol_name.c_str(), version.c_str());
if (ptr.m_void == nullptr)
throw std::runtime_error(std::string("Dl::symbol(\"" + symbol_name +
"\", \"" + version + "\"): ") +
dlerror());
return *ptr.m_real;
}
// Dladdr() is not yet supported in a meaningful way.
#endif // _GNU_SOURCE
private:
Dl(Dl const &);
Dl operator=(Dl const &);
void *m_library; // Pointer to the opened library file
};
#endif // LIBDLMM_DL_HH