diff options
author | Mike Buland <eichlan@xagasoft.com> | 2012-11-05 22:41:51 +0000 |
---|---|---|
committer | Mike Buland <eichlan@xagasoft.com> | 2012-11-05 22:41:51 +0000 |
commit | ec05778d5718a7912e506764d443a78d6a6179e3 (patch) | |
tree | 78a9a01532180030c095acefc45763f07c14edb8 /src/stable/plugger.h | |
parent | b20414ac1fe80a71a90601f4cd1767fa7014a9ba (diff) | |
download | libbu++-ec05778d5718a7912e506764d443a78d6a6179e3.tar.gz libbu++-ec05778d5718a7912e506764d443a78d6a6179e3.tar.bz2 libbu++-ec05778d5718a7912e506764d443a78d6a6179e3.tar.xz libbu++-ec05778d5718a7912e506764d443a78d6a6179e3.zip |
Converted tabs to spaces with tabconv.
Diffstat (limited to '')
-rw-r--r-- | src/stable/plugger.h | 420 |
1 files changed, 210 insertions, 210 deletions
diff --git a/src/stable/plugger.h b/src/stable/plugger.h index d9eaf34..424613f 100644 --- a/src/stable/plugger.h +++ b/src/stable/plugger.h | |||
@@ -24,59 +24,59 @@ | |||
24 | 24 | ||
25 | namespace Bu | 25 | namespace Bu |
26 | { | 26 | { |
27 | subExceptionDecl( PluginException ); | 27 | subExceptionDecl( PluginException ); |
28 | 28 | ||
29 | typedef struct PluginInfo | 29 | typedef struct PluginInfo |
30 | { | 30 | { |
31 | const char *sID; | 31 | const char *sID; |
32 | const char *sAuthor; | 32 | const char *sAuthor; |
33 | unsigned short nVersion; | 33 | unsigned short nVersion; |
34 | unsigned short nRevision; | 34 | unsigned short nRevision; |
35 | void *(*createPlugin)(); | 35 | void *(*createPlugin)(); |
36 | void (*destroyPlugin)( void * ); | 36 | void (*destroyPlugin)( void * ); |
37 | } PluginInfo; | 37 | } PluginInfo; |
38 | 38 | ||
39 | typedef struct PluginReg | 39 | typedef struct PluginReg |
40 | { | 40 | { |
41 | bool bBuiltin; | 41 | bool bBuiltin; |
42 | #ifdef WIN32 | 42 | #ifdef WIN32 |
43 | HMODULE dlHandle; | 43 | HMODULE dlHandle; |
44 | #else | 44 | #else |
45 | void *dlHandle; | 45 | void *dlHandle; |
46 | #endif | 46 | #endif |
47 | PluginInfo *pInfo; | 47 | PluginInfo *pInfo; |
48 | } PluginReg; | 48 | } PluginReg; |
49 | 49 | ||
50 | #define PluginInterface( classname, baseclass, name, ver, rev ) \ | 50 | #define PluginInterface( classname, baseclass, name, ver, rev ) \ |
51 | extern "C" { \ | 51 | extern "C" { \ |
52 | baseclass *create ##classname() \ | 52 | baseclass *create ##classname() \ |
53 | { \ | 53 | { \ |
54 | return new classname(); \ | 54 | return new classname(); \ |
55 | } \ | 55 | } \ |
56 | void destroy ##classname( baseclass *pCls ) \ | 56 | void destroy ##classname( baseclass *pCls ) \ |
57 | { \ | 57 | { \ |
58 | delete pCls; \ | 58 | delete pCls; \ |
59 | } \ | 59 | } \ |
60 | Bu::PluginInfo classname = { \ | 60 | Bu::PluginInfo classname = { \ |
61 | #classname, name, ver, rev, \ | 61 | #classname, name, ver, rev, \ |
62 | create ##classname, destroy ##classname }; \ | 62 | create ##classname, destroy ##classname }; \ |
63 | } | 63 | } |
64 | 64 | ||
65 | #define PluginInterface2( pluginname, classname, baseclass, name, ver, rev ) \ | 65 | #define PluginInterface2( pluginname, classname, baseclass, name, ver, rev ) \ |
66 | extern "C" { \ | 66 | extern "C" { \ |
67 | baseclass *create ##classname() \ | 67 | baseclass *create ##classname() \ |
68 | { \ | 68 | { \ |
69 | return new classname(); \ | 69 | return new classname(); \ |
70 | } \ | 70 | } \ |
71 | void destroy ##classname( baseclass *pCls ) \ | 71 | void destroy ##classname( baseclass *pCls ) \ |
72 | { \ | 72 | { \ |
73 | delete pCls; \ | 73 | delete pCls; \ |
74 | } \ | 74 | } \ |
75 | Bu::PluginInfo pluginname = { \ | 75 | Bu::PluginInfo pluginname = { \ |
76 | #pluginname, name, ver, rev, \ | 76 | #pluginname, name, ver, rev, \ |
77 | (void *(*)())(create ##classname), \ | 77 | (void *(*)())(create ##classname), \ |
78 | (void (*)( void * ))(destroy ##classname) }; \ | 78 | (void (*)( void * ))(destroy ##classname) }; \ |
79 | } | 79 | } |
80 | 80 | ||
81 | // | 81 | // |
82 | // This is probably the main interface to use, I'll describe it some here... | 82 | // This is probably the main interface to use, I'll describe it some here... |
@@ -93,197 +93,197 @@ namespace Bu | |||
93 | // rev - an integer revision number for the plugin | 93 | // rev - an integer revision number for the plugin |
94 | // | 94 | // |
95 | #define PluginInterface3( structname, pluginname, classname, baseclass, name, ver, rev ) \ | 95 | #define PluginInterface3( structname, pluginname, classname, baseclass, name, ver, rev ) \ |
96 | extern "C" { \ | 96 | extern "C" { \ |
97 | baseclass *create ##classname() \ | 97 | baseclass *create ##classname() \ |
98 | { \ | 98 | { \ |
99 | return new classname(); \ | 99 | return new classname(); \ |
100 | } \ | 100 | } \ |
101 | void destroy ##classname( baseclass *pCls ) \ | 101 | void destroy ##classname( baseclass *pCls ) \ |
102 | { \ | 102 | { \ |
103 | delete pCls; \ | 103 | delete pCls; \ |
104 | } \ | 104 | } \ |
105 | Bu::PluginInfo structname = { \ | 105 | Bu::PluginInfo structname = { \ |
106 | #pluginname, name, ver, rev, \ | 106 | #pluginname, name, ver, rev, \ |
107 | (void *(*)())(create ##classname), \ | 107 | (void *(*)())(create ##classname), \ |
108 | (void (*)( void * ))(destroy ##classname) }; \ | 108 | (void (*)( void * ))(destroy ##classname) }; \ |
109 | } | 109 | } |
110 | 110 | ||
111 | /** | 111 | /** |
112 | * A complete dynamic plugin manager system. This will allow you to design | 112 | * A complete dynamic plugin manager system. This will allow you to design |
113 | * and use plugins that are compiled into your program and dynamically | 113 | * and use plugins that are compiled into your program and dynamically |
114 | * linked to your program interchangably. It works on windows and on *nix | 114 | * linked to your program interchangably. It works on windows and on *nix |
115 | * and bsd type systems (anything that supports dlopen). Basically you | 115 | * and bsd type systems (anything that supports dlopen). Basically you |
116 | * create a base class that will be the basic interface of your plugins. | 116 | * create a base class that will be the basic interface of your plugins. |
117 | * Then you create some classes that inherit from it, and use the | 117 | * Then you create some classes that inherit from it, and use the |
118 | * PluginInterface3 macro to create the required data structures for it. | 118 | * PluginInterface3 macro to create the required data structures for it. |
119 | * | 119 | * |
120 | * Once you have plugins you can create a Plugger, by passing in the base | 120 | * Once you have plugins you can create a Plugger, by passing in the base |
121 | * class as it's template parameter. Once it's created, you can register | 121 | * class as it's template parameter. Once it's created, you can register |
122 | * plugins. To register a plugin that is builtin, you just need to pass | 122 | * plugins. To register a plugin that is builtin, you just need to pass |
123 | * a pointer to it's interface structure to the registerBuiltinPlugin | 123 | * a pointer to it's interface structure to the registerBuiltinPlugin |
124 | * function. To register a plugin that is in a shared object or dll file | 124 | * function. To register a plugin that is in a shared object or dll file |
125 | * you just pass the filename (with path, probably), and the name of the | 125 | * you just pass the filename (with path, probably), and the name of the |
126 | * structure to load and you're all set. | 126 | * structure to load and you're all set. |
127 | * | 127 | * |
128 | * To instantiate an object from a plugin simply call instantiate with the | 128 | * To instantiate an object from a plugin simply call instantiate with the |
129 | * name of the plugin as specified in the interface macro. To destroy an | 129 | * name of the plugin as specified in the interface macro. To destroy an |
130 | * object crated with the plugger do not delete it, instead pass it into | 130 | * object crated with the plugger do not delete it, instead pass it into |
131 | * Plugger's destroy function. | 131 | * Plugger's destroy function. |
132 | * | 132 | * |
133 | * Any objects not destroyed when the plugger is deleted will be destroyed | 133 | * Any objects not destroyed when the plugger is deleted will be destroyed |
134 | * automatically. | 134 | * automatically. |
135 | * | 135 | * |
136 | * It is important to note that some systems (linux at least) partition off | 136 | * It is important to note that some systems (linux at least) partition off |
137 | * the memory allocated by objects linked in at run time into a seperate | 137 | * the memory allocated by objects linked in at run time into a seperate |
138 | * segment that, while it can be accessed by the main program, cannot be | 138 | * segment that, while it can be accessed by the main program, cannot be |
139 | * safely or reliably freed by the main program. With that in mind it is | 139 | * safely or reliably freed by the main program. With that in mind it is |
140 | * a good idea to free all memory allocated by a plugin object in the plugin | 140 | * a good idea to free all memory allocated by a plugin object in the plugin |
141 | * object and not allow the calling program to delete it. | 141 | * object and not allow the calling program to delete it. |
142 | */ | 142 | */ |
143 | template<class T> | 143 | template<class T> |
144 | class Plugger | 144 | class Plugger |
145 | { | 145 | { |
146 | public: | 146 | public: |
147 | typedef Bu::Hash<Bu::String, PluginReg *> PluginHash; | 147 | typedef Bu::Hash<Bu::String, PluginReg *> PluginHash; |
148 | typedef Bu::Hash<ptrdiff_t, void *> InstHash; | 148 | typedef Bu::Hash<ptrdiff_t, void *> InstHash; |
149 | 149 | ||
150 | public: | 150 | public: |
151 | Plugger() | 151 | Plugger() |
152 | { | 152 | { |
153 | } | 153 | } |
154 | 154 | ||
155 | virtual ~Plugger() | 155 | virtual ~Plugger() |
156 | { | 156 | { |
157 | for( InstHash::iterator i = hObj.begin(); i != hObj.end(); i++ ) | 157 | for( InstHash::iterator i = hObj.begin(); i != hObj.end(); i++ ) |
158 | { | 158 | { |
159 | T *pPlug = (T *)i.getKey(); | 159 | T *pPlug = (T *)i.getKey(); |
160 | PluginReg *pReg = (PluginReg *)*i; | 160 | PluginReg *pReg = (PluginReg *)*i; |
161 | pReg->pInfo->destroyPlugin( pPlug ); | 161 | pReg->pInfo->destroyPlugin( pPlug ); |
162 | } | 162 | } |
163 | 163 | ||
164 | for( PluginHash::iterator i = hPlugin.begin(); | 164 | for( PluginHash::iterator i = hPlugin.begin(); |
165 | i != hPlugin.end(); i++ ) | 165 | i != hPlugin.end(); i++ ) |
166 | { | 166 | { |
167 | if( (*i)->bBuiltin == false ) | 167 | if( (*i)->bBuiltin == false ) |
168 | { | 168 | { |
169 | #ifdef WIN32 | 169 | #ifdef WIN32 |
170 | FreeLibrary( (*i)->dlHandle ); | 170 | FreeLibrary( (*i)->dlHandle ); |
171 | #else | 171 | #else |
172 | dlclose( (*i)->dlHandle ); | 172 | dlclose( (*i)->dlHandle ); |
173 | #endif | 173 | #endif |
174 | } | 174 | } |
175 | delete (*i); | 175 | delete (*i); |
176 | } | 176 | } |
177 | } | 177 | } |
178 | 178 | ||
179 | void registerBuiltinPlugin( PluginInfo *pInfo ) | 179 | void registerBuiltinPlugin( PluginInfo *pInfo ) |
180 | { | 180 | { |
181 | PluginReg *pReg = new PluginReg; | 181 | PluginReg *pReg = new PluginReg; |
182 | pReg->bBuiltin = true; | 182 | pReg->bBuiltin = true; |
183 | pReg->pInfo = pInfo; | 183 | pReg->pInfo = pInfo; |
184 | hPlugin.insert( pInfo->sID, pReg ); | 184 | hPlugin.insert( pInfo->sID, pReg ); |
185 | } | 185 | } |
186 | 186 | ||
187 | void registerExternalPlugin( const Bu::String &sFName, | 187 | void registerExternalPlugin( const Bu::String &sFName, |
188 | const Bu::String &sPluginName ) | 188 | const Bu::String &sPluginName ) |
189 | { | 189 | { |
190 | PluginReg *pReg; | 190 | PluginReg *pReg; |
191 | if( hPlugin.has( sPluginName ) ) | 191 | if( hPlugin.has( sPluginName ) ) |
192 | throw Bu::ExceptionBase("A plugin with name '%s' is already " | 192 | throw Bu::ExceptionBase("A plugin with name '%s' is already " |
193 | "loaded.", sPluginName.getStr() ); | 193 | "loaded.", sPluginName.getStr() ); |
194 | 194 | ||
195 | pReg = new PluginReg; | 195 | pReg = new PluginReg; |
196 | 196 | ||
197 | pReg->bBuiltin = false; | 197 | pReg->bBuiltin = false; |
198 | #ifdef WIN32 | 198 | #ifdef WIN32 |
199 | pReg->dlHandle = LoadLibrary( sFName.getStr() ); | 199 | pReg->dlHandle = LoadLibrary( sFName.getStr() ); |
200 | if( pReg->dlHandle == NULL ) | 200 | if( pReg->dlHandle == NULL ) |
201 | { | 201 | { |
202 | throw PluginException( 1, "Error opening %s: %s", | 202 | throw PluginException( 1, "Error opening %s: %s", |
203 | sFName.getStr(), Bu::getLastWinError().getStr() ); | 203 | sFName.getStr(), Bu::getLastWinError().getStr() ); |
204 | } | 204 | } |
205 | pReg->pInfo = (PluginInfo *)GetProcAddress( pReg->dlHandle, | 205 | pReg->pInfo = (PluginInfo *)GetProcAddress( pReg->dlHandle, |
206 | sPluginName.getStr() ); | 206 | sPluginName.getStr() ); |
207 | if( pReg->pInfo == NULL ) | 207 | if( pReg->pInfo == NULL ) |
208 | { | 208 | { |
209 | throw PluginException( 2, "Error mapping %s: %s", | 209 | throw PluginException( 2, "Error mapping %s: %s", |
210 | sFName.getStr(), Bu::getLastWinError().getStr() ); | 210 | sFName.getStr(), Bu::getLastWinError().getStr() ); |
211 | } | 211 | } |
212 | #else | 212 | #else |
213 | pReg->dlHandle = dlopen( sFName.getStr(), RTLD_NOW ); | 213 | pReg->dlHandle = dlopen( sFName.getStr(), RTLD_NOW ); |
214 | if( pReg->dlHandle == NULL ) | 214 | if( pReg->dlHandle == NULL ) |
215 | { | 215 | { |
216 | throw PluginException( 1, "Error opening %s: %s", | 216 | throw PluginException( 1, "Error opening %s: %s", |
217 | sFName.getStr(), dlerror() ); | 217 | sFName.getStr(), dlerror() ); |
218 | } | 218 | } |
219 | pReg->pInfo = (PluginInfo *)dlsym( pReg->dlHandle, | 219 | pReg->pInfo = (PluginInfo *)dlsym( pReg->dlHandle, |
220 | sPluginName.getStr() ); | 220 | sPluginName.getStr() ); |
221 | if( pReg->pInfo == NULL ) | 221 | if( pReg->pInfo == NULL ) |
222 | { | 222 | { |
223 | throw PluginException( 2, "Error mapping %s: %s", | 223 | throw PluginException( 2, "Error mapping %s: %s", |
224 | sFName.getStr(), dlerror() ); | 224 | sFName.getStr(), dlerror() ); |
225 | } | 225 | } |
226 | #endif | 226 | #endif |
227 | hPlugin.insert( pReg->pInfo->sID, pReg ); | 227 | hPlugin.insert( pReg->pInfo->sID, pReg ); |
228 | } | 228 | } |
229 | 229 | ||
230 | T *instantiate( const Bu::String &lpName ) | 230 | T *instantiate( const Bu::String &lpName ) |
231 | { | 231 | { |
232 | PluginReg *pReg = (PluginReg *)hPlugin[lpName]; | 232 | PluginReg *pReg = (PluginReg *)hPlugin[lpName]; |
233 | if( pReg == NULL ) | 233 | if( pReg == NULL ) |
234 | return NULL; | 234 | return NULL; |
235 | 235 | ||
236 | T *p = (T *)pReg->pInfo->createPlugin(); | 236 | T *p = (T *)pReg->pInfo->createPlugin(); |
237 | hObj.insert( (ptrdiff_t)p, pReg ); | 237 | hObj.insert( (ptrdiff_t)p, pReg ); |
238 | //printf("pReg: %08X, pPlug: %08X\n", pReg, p ); | 238 | //printf("pReg: %08X, pPlug: %08X\n", pReg, p ); |
239 | 239 | ||
240 | return p; | 240 | return p; |
241 | } | 241 | } |
242 | 242 | ||
243 | bool hasPlugin( const Bu::String &lpName ) | 243 | bool hasPlugin( const Bu::String &lpName ) |
244 | { | 244 | { |
245 | return hPlugin.has( lpName ); | 245 | return hPlugin.has( lpName ); |
246 | } | 246 | } |
247 | 247 | ||
248 | void destroy( T *pPlug ) | 248 | void destroy( T *pPlug ) |
249 | { | 249 | { |
250 | PluginReg *pReg = (PluginReg *)hObj.get((ptrdiff_t)pPlug); | 250 | PluginReg *pReg = (PluginReg *)hObj.get((ptrdiff_t)pPlug); |
251 | //printf("pReg: %08X, pPlug: %08X\n", pReg, pPlug ); | 251 | //printf("pReg: %08X, pPlug: %08X\n", pReg, pPlug ); |
252 | if( pReg == NULL ) | 252 | if( pReg == NULL ) |
253 | return; | 253 | return; |
254 | 254 | ||
255 | pReg->pInfo->destroyPlugin( pPlug ); | 255 | pReg->pInfo->destroyPlugin( pPlug ); |
256 | 256 | ||
257 | hObj.erase( (ptrdiff_t)pPlug ); | 257 | hObj.erase( (ptrdiff_t)pPlug ); |
258 | } | 258 | } |
259 | 259 | ||
260 | void unloadAll() | 260 | void unloadAll() |
261 | { | 261 | { |
262 | for( PluginHash::iterator i = hPlugin.begin(); | 262 | for( PluginHash::iterator i = hPlugin.begin(); |
263 | i != hPlugin.end(); i++ ) | 263 | i != hPlugin.end(); i++ ) |
264 | { | 264 | { |
265 | if( (*i)->bBuiltin == false ) | 265 | if( (*i)->bBuiltin == false ) |
266 | { | 266 | { |
267 | #ifdef WIN32 | 267 | #ifdef WIN32 |
268 | FreeLibrary( (*i)->dlHandle ); | 268 | FreeLibrary( (*i)->dlHandle ); |
269 | #else | 269 | #else |
270 | dlclose( (*i)->dlHandle ); | 270 | dlclose( (*i)->dlHandle ); |
271 | #endif | 271 | #endif |
272 | } | 272 | } |
273 | delete (*i); | 273 | delete (*i); |
274 | } | 274 | } |
275 | hPlugin.clear(); | 275 | hPlugin.clear(); |
276 | } | 276 | } |
277 | 277 | ||
278 | Bu::List<Bu::String> getPluginList() | 278 | Bu::List<Bu::String> getPluginList() |
279 | { | 279 | { |
280 | return hPlugin.getKeys(); | 280 | return hPlugin.getKeys(); |
281 | } | 281 | } |
282 | 282 | ||
283 | private: | 283 | private: |
284 | PluginHash hPlugin; | 284 | PluginHash hPlugin; |
285 | InstHash hObj; | 285 | InstHash hObj; |
286 | }; | 286 | }; |
287 | } | 287 | } |
288 | 288 | ||
289 | #endif | 289 | #endif |