aboutsummaryrefslogtreecommitdiff
path: root/src/plugger.h
diff options
context:
space:
mode:
Diffstat (limited to 'src/plugger.h')
-rw-r--r--src/plugger.h196
1 files changed, 196 insertions, 0 deletions
diff --git a/src/plugger.h b/src/plugger.h
new file mode 100644
index 0000000..98d4ecc
--- /dev/null
+++ b/src/plugger.h
@@ -0,0 +1,196 @@
1#ifndef PLUGGER_H
2#define PLUGGER_H
3
4
5#include "bu/hash.h"
6#include "bu/list.h"
7#include <dlfcn.h>
8#include "bu/exceptions.h"
9#include "bu/fstring.h"
10
11namespace Bu
12{
13 typedef struct PluginInfo
14 {
15 const char *sID;
16 const char *sAuthor;
17 unsigned short nVersion;
18 unsigned short nRevision;
19 void *(*createPlugin)();
20 void (*destroyPlugin)( void * );
21 } PluginInfo;
22
23 typedef struct PluginReg
24 {
25 bool bBuiltin;
26 void *dlHandle;
27 PluginInfo *pInfo;
28 } PluginReg;
29
30#define PluginInterface( classname, baseclass, name, ver, rev ) \
31 extern "C" { \
32 baseclass *create ##classname() \
33 { \
34 return new classname(); \
35 } \
36 void destroy ##classname( baseclass *pCls ) \
37 { \
38 delete pCls; \
39 } \
40 PluginInfo classname = { \
41 #classname, name, ver, rev, \
42 create ##classname, destroy ##classname }; \
43 }
44
45#define PluginInterface2( pluginname, classname, baseclass, name, ver, rev ) \
46 extern "C" { \
47 baseclass *create ##classname() \
48 { \
49 return new classname(); \
50 } \
51 void destroy ##classname( baseclass *pCls ) \
52 { \
53 delete pCls; \
54 } \
55 PluginInfo pluginname = { \
56 #pluginname, name, ver, rev, \
57 (void *(*)())(create ##classname), \
58 (void (*)( void * ))(destroy ##classname) }; \
59 }
60
61#define PluginInterface3( structname, pluginname, classname, baseclass, name, ver, rev ) \
62 extern "C" { \
63 baseclass *create ##classname() \
64 { \
65 return new classname(); \
66 } \
67 void destroy ##classname( baseclass *pCls ) \
68 { \
69 delete pCls; \
70 } \
71 PluginInfo structname = { \
72 #pluginname, name, ver, rev, \
73 (void *(*)())(create ##classname), \
74 (void (*)( void * ))(destroy ##classname) }; \
75 }
76
77 template<class T>
78 class Plugger
79 {
80 public:
81 typedef Bu::Hash<Bu::FString, PluginReg *> PluginHash;
82 typedef Bu::Hash<int, void *> InstHash;
83
84 public:
85 Plugger()
86 {
87 }
88
89 virtual ~Plugger()
90 {
91 for( InstHash::iterator i = hObj.begin(); i != hObj.end(); i++ )
92 {
93 T *pPlug = (T *)i.getKey();
94 PluginReg *pReg = (PluginReg *)*i;
95 pReg->pInfo->destroyPlugin( pPlug );
96 }
97
98 for( PluginHash::iterator i = hPlugin.begin();
99 i != hPlugin.end(); i++ )
100 {
101 if( (*i)->bBuiltin == false )
102 {
103 dlclose( (*i)->dlHandle );
104 }
105 delete (*i);
106 }
107 }
108
109 void registerBuiltinPlugin( PluginInfo *pInfo )
110 {
111 PluginReg *pReg = new PluginReg;
112 pReg->bBuiltin = true;
113 pReg->pInfo = pInfo;
114 hPlugin.insert( pInfo->sID, pReg );
115 }
116
117 void registerExternalPlugin( const char *sFName, const char *sPluginName )
118 {
119 PluginReg *pReg = (PluginReg *)hPlugin[sPluginName];
120 if( pReg != NULL )
121 {
122 hPlugin.erase( sPluginName );
123 dlclose( pReg->dlHandle );
124 delete pReg;
125 pReg = NULL;
126 }
127
128 pReg = new PluginReg;
129
130 pReg->bBuiltin = false;
131 pReg->dlHandle = dlopen( sFName, RTLD_NOW );
132 if( pReg->dlHandle == NULL )
133 {
134 throw PluginException( 1, "Error on %s: %s", sFName, dlerror() );
135 }
136 pReg->pInfo = (PluginInfo *)dlsym( pReg->dlHandle, sPluginName );
137 if( pReg->pInfo == NULL )
138 {
139 throw PluginException( 2, "Error on %s: %s", sFName, dlerror() );
140 }
141 hPlugin.insert( pReg->pInfo->sID, pReg );
142 }
143
144 T *instantiate( const char *lpName )
145 {
146 PluginReg *pReg = (PluginReg *)hPlugin[lpName];
147 if( pReg == NULL )
148 return NULL;
149
150 T *p = (T *)pReg->pInfo->createPlugin();
151 hObj.insert( p, pReg );
152 //printf("pReg: %08X, pPlug: %08X\n", pReg, p );
153
154 return p;
155 }
156
157 bool hasPlugin( const char *lpName )
158 {
159 if( hPlugin[lpName] == NULL )
160 return false;
161 return true;
162 }
163
164 void destroy( T *pPlug )
165 {
166 PluginReg *pReg = (PluginReg *)hObj[pPlug];
167 //printf("pReg: %08X, pPlug: %08X\n", pReg, pPlug );
168 if( pReg == NULL )
169 return;
170
171 pReg->pInfo->destroyPlugin( pPlug );
172
173 hObj.erase( pPlug );
174 }
175
176 void unloadAll()
177 {
178 for( PluginHash::iterator i = hPlugin.begin();
179 i != hPlugin.end(); i++ )
180 {
181 if( (*i)->bBuiltin == false )
182 {
183 dlclose( (*i)->dlHandle );
184 }
185 delete (*i);
186 }
187 hPlugin.clear();
188 }
189
190 private:
191 PluginHash hPlugin;
192 InstHash hObj;
193 };
194}
195
196#endif