-
Notifications
You must be signed in to change notification settings - Fork 49
/
choc_DynamicLibrary.h
172 lines (140 loc) · 6.18 KB
/
choc_DynamicLibrary.h
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
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
//
// ██████ ██ ██ ██████ ██████
// ██ ██ ██ ██ ██ ██ ** Classy Header-Only Classes **
// ██ ███████ ██ ██ ██
// ██ ██ ██ ██ ██ ██ https://github.com/Tracktion/choc
// ██████ ██ ██ ██████ ██████
//
// CHOC is (C)2022 Tracktion Corporation, and is offered under the terms of the ISC license:
//
// Permission to use, copy, modify, and/or distribute this software for any purpose with or
// without fee is hereby granted, provided that the above copyright notice and this permission
// notice appear in all copies. THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL
// WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
// AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR
// CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS,
// WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN
// CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
#ifndef CHOC_DYNAMIC_LIBRARY_HEADER_INCLUDED
#define CHOC_DYNAMIC_LIBRARY_HEADER_INCLUDED
#include <string>
namespace choc::file
{
//==============================================================================
/**
A minimal cross-platform loader for .dll/.so files.
*/
struct DynamicLibrary
{
DynamicLibrary() = default;
/// Attempts to load a library with the given name or path.
DynamicLibrary (std::string_view library);
DynamicLibrary (const DynamicLibrary&) = delete;
DynamicLibrary& operator= (const DynamicLibrary&) = delete;
DynamicLibrary (DynamicLibrary&&);
DynamicLibrary& operator= (DynamicLibrary&&);
/// On destruction, this object releases the library that was loaded
~DynamicLibrary();
/// Returns a pointer to the function with this name, or nullptr if not found.
void* findFunction (std::string_view functionName);
/// Returns true if the library was successfully loaded
operator bool() const noexcept { return handle != nullptr; }
/// Releases any handle that this object is holding
void close();
/// platform-specific handle. Will be nullptr if not loaded
void* handle = nullptr;
};
//==============================================================================
// _ _ _ _
// __| | ___ | |_ __ _ (_)| | ___
// / _` | / _ \| __| / _` || || |/ __|
// | (_| || __/| |_ | (_| || || |\__ \ _ _ _
// \__,_| \___| \__| \__,_||_||_||___/(_)(_)(_)
//
// Code beyond this point is implementation detail...
//
//==============================================================================
inline DynamicLibrary::~DynamicLibrary()
{
close();
}
inline DynamicLibrary::DynamicLibrary (DynamicLibrary&& other) : handle (other.handle)
{
other.handle = nullptr;
}
inline DynamicLibrary& DynamicLibrary::operator= (DynamicLibrary&& other)
{
close();
handle = other.handle;
other.handle = nullptr;
return *this;
}
} // namespace choc::file
#if ! (defined (_WIN32) || defined (_WIN64))
#include <dlfcn.h>
inline choc::file::DynamicLibrary::DynamicLibrary (std::string_view library)
{
handle = ::dlopen (std::string (library).c_str(), RTLD_LOCAL | RTLD_NOW);
}
inline void choc::file::DynamicLibrary::close()
{
if (handle != nullptr)
{
::dlclose (handle);
handle = nullptr;
}
}
inline void* choc::file::DynamicLibrary::findFunction (std::string_view name)
{
if (handle != nullptr)
return ::dlsym (handle, std::string (name).c_str());
return {};
}
#else
//==============================================================================
namespace choc::win32_defs
{
#if ! (defined (_WINDOWS_) || defined (_APISETLIBLOADER_)) // only use these local definitions if windows.h isn't already included
using CHOC_HMODULE = void*;
#ifdef _MSC_VER
extern "C" CHOC_HMODULE __stdcall choc_LoadLibraryA (const char*);
extern "C" int __stdcall choc_FreeLibrary (CHOC_HMODULE);
extern "C" void* __stdcall choc_GetProcAddress (CHOC_HMODULE, const char*);
#pragma comment(linker,"/alternatename:choc_LoadLibraryA=LoadLibraryA")
#pragma comment(linker,"/alternatename:choc_FreeLibrary=FreeLibrary")
#pragma comment(linker,"/alternatename:choc_GetProcAddress=GetProcAddress")
static inline CHOC_HMODULE LoadLibraryA (const char* l) { return choc_LoadLibraryA (l); }
static inline int FreeLibrary (CHOC_HMODULE m) { return choc_FreeLibrary (m); }
static inline void* GetProcAddress (CHOC_HMODULE m, const char* f) { return choc_GetProcAddress (m, f); }
#else
extern "C" __declspec(dllimport) CHOC_HMODULE __stdcall LoadLibraryA (const char*);
extern "C" __declspec(dllimport) int __stdcall FreeLibrary (CHOC_HMODULE);
extern "C" __declspec(dllimport) void* __stdcall GetProcAddress (CHOC_HMODULE, const char*);
#endif
#else
using CHOC_HMODULE = HMODULE;
static inline CHOC_HMODULE LoadLibraryA (const char* l) { return ::LoadLibraryA (l); }
static inline int FreeLibrary (CHOC_HMODULE m) { return ::FreeLibrary (m); }
static inline void* GetProcAddress (CHOC_HMODULE m, const char* f) { return (void*) ::GetProcAddress (m, f); }
#endif
}
inline choc::file::DynamicLibrary::DynamicLibrary (std::string_view library)
{
handle = (void*) win32_defs::LoadLibraryA (std::string (library).c_str());
}
inline void choc::file::DynamicLibrary::close()
{
if (handle != nullptr)
{
win32_defs::FreeLibrary ((win32_defs::CHOC_HMODULE) handle);
handle = nullptr;
}
}
inline void* choc::file::DynamicLibrary::findFunction (std::string_view name)
{
if (handle != nullptr)
return (void*) win32_defs::GetProcAddress ((win32_defs::CHOC_HMODULE) handle, std::string (name).c_str());
return {};
}
#endif
#endif // CHOC_DYNAMIC_LIBRARY_HEADER_INCLUDED