aboutsummaryrefslogtreecommitdiff
path: root/src/stable/plugger.h
diff options
context:
space:
mode:
Diffstat (limited to 'src/stable/plugger.h')
-rw-r--r--src/stable/plugger.h420
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
25namespace Bu 25namespace 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