forked from KhronosGroup/ANARI-SDK
-
Notifications
You must be signed in to change notification settings - Fork 0
/
LibraryImpl.cpp
221 lines (179 loc) · 5.02 KB
/
LibraryImpl.cpp
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
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
// Copyright 2021-2024 The Khronos Group
// SPDX-License-Identifier: Apache-2.0
#include "anari/backend/LibraryImpl.h"
// std
#ifdef _WIN32
#ifndef WIN32_LEAN_AND_MEAN
#define WIN32_LEAN_AND_MEAN
#endif
#include <windows.h>
#else
#include <dlfcn.h>
#include <sys/times.h>
#endif
#include <stdexcept>
#include <vector>
#if defined(__MACOSX__) || defined(__APPLE__)
#define RKCOMMON_LIB_EXT ".dylib"
#else
#define RKCOMMON_LIB_EXT ".so"
#endif
#ifdef _WIN32
#define LOOKUP_SYM(lib, symbol) (void*)GetProcAddress((HMODULE)lib, symbol.c_str());
#define FREE_LIB(lib) FreeLibrary((HMODULE)lib);
#else
#define LOOKUP_SYM(lib, symbol) dlsym(lib, symbol.c_str());
#define FREE_LIB(lib) dlclose(lib)
#endif
/* Export a symbol to ask the dynamic loader about in order to locate this
* library at runtime. */
extern "C" int _anari_anchor()
{
return 0;
}
namespace {
std::string library_location()
{
#if defined(_WIN32) && !defined(__CYGWIN__)
MEMORY_BASIC_INFORMATION mbi;
VirtualQuery((LPCVOID)&_anari_anchor, &mbi, sizeof(mbi));
char pathBuf[16384];
if (!GetModuleFileNameA(
static_cast<HMODULE>(mbi.AllocationBase), pathBuf, sizeof(pathBuf)))
return std::string();
std::string path = std::string(pathBuf);
path.resize(path.rfind('\\') + 1);
#else
const char *anchor = "_anari_anchor";
void *handle = dlsym(RTLD_DEFAULT, anchor);
if (!handle)
return std::string();
Dl_info di;
int ret = dladdr(handle, &di);
if (!ret || !di.dli_saddr || !di.dli_fname)
return std::string();
std::string path = std::string(di.dli_fname);
path.resize(path.rfind('/') + 1);
#endif
return path;
}
} // namespace
namespace anari {
using InitFcn = void (*)();
using AllocFcn = void *(*)();
static std::vector<void *> g_loadedLibs;
static void *loadLibrary(
const std::string &libName, bool withAnchor, std::string &errorMessage)
{
std::string file = libName;
std::string errorMsg;
std::string libLocation = withAnchor ? library_location() : std::string();
void *lib = nullptr;
#ifdef _WIN32
// Set cwd to library location, to make sure dependent libraries are found as
// well
constexpr int MAX_DIRSIZE = 4096;
TCHAR currentWd[MAX_DIRSIZE];
DWORD dwRet = 0;
if (withAnchor)
dwRet = GetCurrentDirectory(MAX_DIRSIZE, currentWd);
if (dwRet > MAX_DIRSIZE)
errorMsg = "library path larger than " + std::to_string(MAX_DIRSIZE)
+ " characters";
else if (withAnchor && dwRet == 0)
errorMsg = "GetCurrentDirectory() failed for unknown reason";
else {
SetCurrentDirectory(libLocation.c_str());
// Load the library
std::string fullName = libLocation + file + ".dll";
lib = LoadLibrary(fullName.c_str());
if (lib == nullptr) {
DWORD err = GetLastError();
LPTSTR lpMsgBuf;
FormatMessage(FORMAT_MESSAGE_ALLOCATE_BUFFER | FORMAT_MESSAGE_FROM_SYSTEM
| FORMAT_MESSAGE_IGNORE_INSERTS,
NULL,
err,
MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT),
(LPTSTR)&lpMsgBuf,
0,
NULL);
errorMsg = lpMsgBuf;
LocalFree(lpMsgBuf);
}
// Change cwd back to its original value
SetCurrentDirectory(currentWd);
}
#else
std::string fullName = libLocation + "lib" + file + RKCOMMON_LIB_EXT;
lib = dlopen(fullName.c_str(), RTLD_LAZY | RTLD_LOCAL);
if (lib == nullptr) {
errorMsg += dlerror();
}
#endif
if (lib == nullptr) {
errorMessage += " could not open library lib " + libName + ": " + errorMsg;
}
return lib;
}
void *loadANARILibrary(const std::string &libName)
{
std::string errorMessage;
void *lib = loadLibrary(libName, false, errorMessage);
if (!lib) {
errorMessage = "(unanchored library load attempt failed)\n";
lib = loadLibrary(libName, true, errorMessage);
}
if (!lib)
throw std::runtime_error(errorMessage);
return lib;
}
void *getSymbolAddress(void *lib, const std::string &symbol)
{
return LOOKUP_SYM(lib, symbol);
}
void freeLibrary(void *lib)
{
if (lib)
FREE_LIB(lib);
}
///////////////////////////////////////////////////////////////////////////////
// LibraryImpl definitions ////////////////////////////////////////////////////
///////////////////////////////////////////////////////////////////////////////
LibraryImpl::LibraryImpl(
void *lib, ANARIStatusCallback defaultStatusCB, const void *statusCBPtr)
: m_lib(lib),
m_defaultStatusCB(defaultStatusCB),
m_defaultStatusCBUserPtr(statusCBPtr)
{}
LibraryImpl::~LibraryImpl()
{
freeLibrary(m_lib);
}
void LibraryImpl::loadModule(const char * /*name*/)
{
// no-op
}
void LibraryImpl::unloadModule(const char * /*name*/)
{
// no-op
}
const char **LibraryImpl::getDeviceSubtypes()
{
static const char *subtypes[] = {"default", nullptr};
return subtypes;
}
ANARIStatusCallback LibraryImpl::defaultStatusCB() const
{
return m_defaultStatusCB;
}
const void *LibraryImpl::defaultStatusCBUserPtr() const
{
return m_defaultStatusCBUserPtr;
}
ANARILibrary LibraryImpl::this_library() const
{
return (ANARILibrary)this;
}
ANARI_TYPEFOR_DEFINITION(LibraryImpl *);
} // namespace anari