-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathcore.cpccLinkLibrary.h
More file actions
193 lines (156 loc) · 6.18 KB
/
core.cpccLinkLibrary.h
File metadata and controls
193 lines (156 loc) · 6.18 KB
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
/* ****************************************************
* File: core.cpccLinkLibrary.h
* File version: 1.2
* Dependencies: None
* Purpose: Portable (cross-platform), light-weight class
* to help with the dynamic library loading (.DLL, .dylib)
* and linking of functions
* ****************************************************
* Library: Cross Platform C++ Classes (cpcc)
* Copyright: StarMessage software.
* License: Free for opensource projects.
* Commercial license for closed source projects.
* Web: http://www.starmessagesoftware.com/cpcclibrary/
* https://github.com/starmessage/cpcc
* email: sales -at- starmessage.info
* ****************************************************
*/
#pragma once
// https://en.wikipedia.org/wiki/Dynamic_loading
#include <string>
#include <cstdio>
#include <iostream>
#ifdef _WIN32
#include <windows.h>
#pragma comment(lib, "Kernel32.lib")
#elif defined(__APPLE__)
#include <dlfcn.h>
#endif
#ifdef _WIN32
class cpccLinkedLibraryPortable_Win
{
public:
typedef HMODULE tLibHandle;
static tLibHandle loadLibrary(const TCHAR *aFilename)
{
/*
http://msdn.microsoft.com/en-us/library/ms684175.aspx
If the string specifies a full path, the function searches only that path for the module.
If the string specifies a relative path or a module name without a path, the function uses
a standard search strategy to find the module.
If the string specifies a module name without a path and the
file name extension is omitted, the function appends the default
library extension .dll to the module name. To prevent the function
from appending .dll to the module name, include a trailing point
character (.) in the module name string.
When specifying a path, be sure to use backslashes (\),
not forward slashes (/).
If the function fails, the return value is NULL.
To get extended error information, call GetLastError.
*/
tLibHandle result = LoadLibrary(aFilename);
if (!result)
{
std::cerr << "LoadLibrary(" << aFilename << ") failed. GetLastError=" << GetLastError() << std::endl;
}
return result;
}
static void unloadLibrary(const tLibHandle aHandle)
{
if (aHandle)
FreeLibrary(aHandle);
}
static void *getFunctionAddress(const tLibHandle aHandle, const char * aFunctionName)
{
if (!aHandle) return NULL;
return (void *)GetProcAddress(aHandle, aFunctionName);
}
};
typedef cpccLinkedLibraryPortable_Win cpccLinkedLibradyImpl;
#endif
#ifdef __APPLE__
class cpccLinkedLibraryPortable_OSX
{
public:
typedef void * tLibHandle;
static tLibHandle loadLibrary(const char *aFilename)
{
// https://linux.die.net/man/3/dlerror
// The function dlerror() returns a human readable string describing the most recent error
// that occurred from dlopen(), dlsym() or dlclose() since the last call to dlerror().
tLibHandle result = dlopen(aFilename, RTLD_LAZY);
if (!result)
std::cerr << "#9312a Error during dlopen(" << aFilename <<"): " << dlerror() << std::endl;
return result;
}
static void unloadLibrary(const tLibHandle aHandle)
{
// The function dlclose() decrements the reference count on the dynamic library handle handle.
// If the reference count drops to zero and no other loaded libraries use symbols in it,
// then the dynamic library is unloaded.
// The function dlclose() returns 0 on success, and nonzero on error.
int ret = dlclose(aHandle);
if (ret!=0)
std::cerr << "#9312c Error during dlclose(): " << dlerror() << std::endl;
}
static void *getFunctionAddress(const tLibHandle aHandle, const char * aFunctionName)
{
// Since the value of the symbol could actually be NULL (so that a NULL return from dlsym()
// need not indicate an error), the correct way to test for an error is to
// call dlerror() to clear any old error conditions, then
// call dlsym(), and then
// call dlerror() again, saving its return value into a variable, and check whether this saved value is not NULL.
dlerror();
void *result = dlsym(aHandle, aFunctionName);
if (!result)
std::cerr << "#9312b Error: " << dlerror() << std::endl;
return result;
}
};
typedef cpccLinkedLibraryPortable_OSX cpccLinkedLibradyImpl;
#endif
#ifndef _WIN32
#ifndef TCHAR // for non Windows systems
#define TCHAR char
#endif
#endif
class cpccLinkedLibrary
{
private:
const cpccLinkedLibradyImpl::tLibHandle m_libHandle;
// prevent copy and assignment
cpccLinkedLibrary(const cpccLinkedLibrary&);
cpccLinkedLibrary& operator=(const cpccLinkedLibrary&);
protected:
// cpccLinkedLibradyImpl::tLibHandle getLibHandle(void) const { return m_libHandle; }
public: // ctor, dtor
explicit cpccLinkedLibrary(const TCHAR *aLibraryfilename):
m_libHandle(cpccLinkedLibradyImpl::loadLibrary(aLibraryfilename))
{
if (!m_libHandle)
std::cerr << "#7524: failed to load dynamic library: " << aLibraryfilename << std::endl;
else
std::cout << "Library loaded: " << aLibraryfilename << std::endl;
}
// todo: rule of three
virtual ~cpccLinkedLibrary()
{
if (m_libHandle)
cpccLinkedLibradyImpl::unloadLibrary(m_libHandle);
// m_libHandle = NULL;
};
public: // members
void * getFunction(const char * aFunctionName)
{
if (!isLoaded())
{
std::cerr << "#9771e: Cannot load function: [" << aFunctionName << ("] because the dynamic library was not loaded\n");
return NULL;
}
void *ptr = cpccLinkedLibradyImpl::getFunctionAddress(m_libHandle, aFunctionName);
if (!ptr)
std::cerr << "#9771a: did not find a function [" << aFunctionName << "] in the dynamically loaded library\n";
return ptr;
}
bool isLoaded(void) const { return (m_libHandle != NULL); };
};