summaryrefslogtreecommitdiff
path: root/src/plugger.h
blob: 2cf224e59d200b4f4d1ebbeb91064d89c146279a (plain)
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
#ifndef PLUGGER_H
#define PLUGGER_H

#include "hashtable.h"
#include "list"
#include "hashfunctionstring.h"
#include "hashfunctionint.h"
#include "dlfcn.h"

typedef struct PluginInfo
{
	const char *sID;
	const char *sAuthor;
	unsigned short nVersion;
	unsigned short nRevision;
	class Plugin *(*createPlugin)();
	void (*destroyPlugin)( class Plugin * );
} PluginInfo;

#define PluginInterface( classname, name, ver, rev )					\
extern "C" {															\
	class Plugin *create ##classname()									\
	{																	\
		return new classname();											\
	}																	\
	void destroy ##classname( class Plugin *pCls )						\
	{																	\
		delete pCls;													\
	}																	\
	PluginInfo classname = { #classname, name, ver, rev, 				\
		create ##classname, destroy ##classname };						\
}

typedef struct PluginReg
{
	bool bBuiltin;
	void *dlHandle;
	PluginInfo *pInfo;
} PluginReg;

template<class T>
class Plugger
{
public:
	Plugger() :
		hPlugin( new HashFunctionString(), 11 ),
		hObj( new HashFunctionInt(), 11 )
	{
	}

	virtual ~Plugger()
	{
		std::list<PluginReg *>::iterator i;
		for( i = lPlugin.begin(); i != lPlugin.end(); i++ )
		{
			if( (*i)->bBuiltin == false )
			{
				dlclose( (*i)->dlHandle );
			}
			delete (*i);
		}
	}

	void registerBuiltinPlugin( PluginInfo *pInfo )
	{
		PluginReg *pReg = new PluginReg;
		pReg->bBuiltin = true;
		pReg->pInfo = pInfo;
		lPlugin.insert( lPlugin.end(), pReg );
		hPlugin.insert( pInfo->sID, pReg );
	}

	void registerExternalPlugin( const char *sFName, const char *sPluginName )
	{
		PluginReg *pReg = new PluginReg;
		pReg->bBuiltin = false;
		pReg->dlHandle = dlopen( sFName, RTLD_NOW );
		if( pReg->dlHandle == NULL )
		{
			printf("***ERROR:  %s\n\n", dlerror() );
			exit( 105 );
		}
		pReg->pInfo = (PluginInfo *)dlsym( pReg->dlHandle, sPluginName );
		if( pReg->pInfo == NULL )
		{
			printf("***ERROR:  %s\n\n", dlerror() );
			exit( 106 );
		}
		hPlugin.insert( pReg->pInfo->sID, pReg );
		lPlugin.insert( lPlugin.end(), pReg );
	}

	T *instantiate( const char *lpName )
	{
		PluginReg *pReg = (PluginReg *)hPlugin[lpName];
		if( pReg == NULL )
			return NULL;

		T *p = pReg->pInfo->createPlugin();
		hObj.insert( p, pReg );
		printf("pReg:  %08X, pPlug: %08X\n", pReg, p );
	
		return p;
	}

	void destroy( T *pPlug )
	{
		PluginReg *pReg = (PluginReg *)hObj[pPlug];
		printf("pReg:  %08X, pPlug: %08X\n", pReg, pPlug );
		if( pReg == NULL )
			return;

		pReg->pInfo->destroyPlugin( pPlug );

		hObj.del( pPlug );
	}

private:
	std::list<PluginReg *> lPlugin;
	HashTable hPlugin;
	HashTable hObj;
};

#endif