/
library.h
187 lines (159 loc) · 5.96 KB
/
library.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
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
/*
* The Doomsday Engine Project -- libdeng2
*
* Copyright (c) 2009-2012 Jaakko Keränen <jaakko.keranen@iki.fi>
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, see <http://www.gnu.org/licenses/>.
*/
#ifndef LIBDENG2_LIBRARY_H
#define LIBDENG2_LIBRARY_H
#include "../libdeng2.h"
#include "../String"
#include <QLibrary>
#include <QMap>
/**
* Convenience macro for accessing symbols that have a type defined in de::Library
* with the type name matching the symbol name.
*/
#define DENG2_SYMBOL(Name) symbol<de::Library::Name>(#Name)
namespace de
{
class Audio;
class Map;
class Object;
class User;
class World;
/**
* The Library class allows loading shared library files
* (DLL/so/bundle/dylib) and looks up exported symbols in the libraries.
*
* Library type identifiers;
* - <code>library/generic</code>: A shared library with no special function.
* - <code>deng-plugin/generic</code>: Generic libdeng2 plugin. Loaded always.
* - <code>deng-plugin/game</code>: The game plugin. Only one of these can be loaded.
* - <code>deng-plugin/audio</code>: Audio driver. Optional. Loaded on demand by
* the audio subsystem.
*
* @ingroup core
*/
class DENG2_PUBLIC Library
{
public:
/// Loading the shared library failed. @ingroup errors
DENG2_ERROR(LoadError)
/// A symbol was not found. @ingroup errors
DENG2_ERROR(SymbolMissingError)
/// Default type identifier.
static const char* DEFAULT_TYPE;
// Common function profiles.
/**
* Queries the plugin for a type identifier string. If this function is not
* defined, the identifier defaults to DEFAULT_TYPE.
*
* @return Type identifier string.
*/
typedef const char* (*deng_LibraryType)(void);
/**
* Performs any one-time initialization necessary for the usage of the plugin.
* If this symbol is exported from a shared library, it gets called automatically
* when the library is loaded.
*/
typedef void (*deng_InitializePlugin)(void);
/**
* Frees resources reserved by the plugin. If this symbol is exported from a
* shared library, it gets called automatically when the library is unloaded.
*/
typedef void (*deng_ShutdownPlugin)(void);
/**
* Constructs a new instance of an audio subsystem.
*
* @return Audio subsystem.
*/
typedef Audio* (*deng_NewAudio)(void);
/**
* Constructs a new game world.
*/
typedef World* (*deng_NewWorld)(void);
/**
* Constructs a new game map.
*/
typedef Map* (*deng_NewMap)();
/**
* Constructs a new object.
*/
typedef Object* (*deng_NewObject)(void);
/**
* Constructs a new user.
*/
typedef User* (*deng_NewUser)(void);
typedef dint (*deng_GetInteger)(dint id);
typedef const char* (*deng_GetString)(dint id);
typedef void* (*deng_GetAddress)(dint id);
typedef void (*deng_Ticker)(ddouble tickLength);
public:
/**
* Constructs a new Library by loading a native shared library.
*
* @param nativePath Path of the shared library to load.
*/
Library(const String& nativePath);
/**
* Unloads the shared library.
*/
virtual ~Library();
/**
* Returns the type identifier of the library. This affects how
* libdeng2 will treat the library. The type is determined
* automatically when the library is first loaded, and can then be
* queried at any time even after the library has been unloaded.
*/
const String& type() const { return _type; }
/**
* Gets the address of an exported symbol. This will always return a valid
* pointer to the symbol.
*
* @param name Name of the exported symbol.
*
* @return A pointer to the symbol.
*/
void* address(const String& name);
/**
* Checks if the library exports a specific symbol.
* @param name Name of the exported symbol.
* @return @c true if the symbol is exported, @c false if not.
*/
bool hasSymbol(const String& name) const;
template <typename Type>
Type symbol(const String& name) {
/**
* @note Casting to a pointer-to-function type: see
* http://www.trilithium.com/johan/2004/12/problem-with-dlsym/
*/
// This is not 100% portable to all possible memory architectures; thus:
DENG2_ASSERT(sizeof(void*) == sizeof(Type));
union { void* original; Type target; } forcedCast;
forcedCast.original = address(name);
return forcedCast.target;
}
private:
/// Handle to the shared library.
QLibrary* _library;
typedef QMap<String, void*> Symbols;
Symbols _symbols;
/// Type identifier for the library (e.g., "deng-plugin/generic").
/// Queried by calling deng_LibraryType(), if one is exported in the library.
String _type;
};
}
#endif /* LIBDENG2_LIBRARY_H */