summaryrefslogtreecommitdiff
path: root/include/dynamic.h
blob: f2efce0f0ffb677a75c98959cdbbc22ee9268b2b (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
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
/*       +------------------------------------+
 *       | Inspire Internet Relay Chat Daemon |
 *       +------------------------------------+
 *
 *  InspIRCd: (C) 2002-2007 InspIRCd Development Team
 * See: http://www.inspircd.org/wiki/index.php/Credits
 *
 * This program is free but copyrighted software; see
 *            the file COPYING for details.
 *
 * ---------------------------------------------------
 */

#ifndef __DLL_H
#define __DLL_H

/** This typedef represents the init_module function within each module.
 * The init_module function is the only exported extern "C" declaration
 * in any module file.
 */
typedef void * (initfunc) (void);

#include "inspircd_config.h"

class InspIRCd;

/** The DLLManager class is able to load a module file by filename,
 * and locate its init_module symbol.
 */
class DLLManager
{
 public:
	/** This constructor loads the module using dlopen()
	 * @param ServerInstance The creator class of this object
	 * @param fname The filename to load. This should be within
	 * the modules dir.
	 */
	DLLManager(InspIRCd* ServerInstance, const char *fname);
	virtual ~DLLManager();


#ifdef STATIC_LINK
	/** Get a symbol using static linking.
	 * @param v A static function pointer, pointing at an init_module function
	 * @param sym_name The symbol name to find, usually "init_module"
	 * @return True if the symbol can be found
	 */
	bool GetSymbol(initfunc* &v, const char *sym_name);
#else
	/** Get a symbol using dynamic linking.
	 * @param v A function pointer, pointing at an init_module function
	 * @param sym_name The symbol name to find, usually "init_module"
	 * @return true if the symbol can be found, also the symbol will be put into v.
	 */
	bool GetSymbol(void **v, const char *sym_name);
#endif
	/** Get the last error from dlopen() or dlsym().
	 * @return The last error string, or NULL if no error has occured
	 */
	char* LastError() 
	{
		 return err;
	}

	/** The module handle
	 */
	void *h;

 protected:

	/** The last error string, or NULL
	 */
	char *err;
#ifdef STATIC_LINK

	/** The module name
	 */
	char staticname[1024];
#endif
};

/** This class is a specialized form of DLLManager designed to load InspIRCd modules.
 * It's job is to call the init_module function and receive a factory pointer.
 */
class DLLFactoryBase : public DLLManager
{
 public:
	/** Default constructor.
	 * This constructor loads a module file by calling its DLLManager subclass constructor,
	 * then finds the symbol using DLLManager::GetSymbol(), and calls the symbol,
	 * obtaining a valid pointer to the init_module function
	 */
	DLLFactoryBase(InspIRCd* Instance, const char *fname, const char *func_name = 0);

	/** Default destructor
	 */
	virtual ~DLLFactoryBase();
#ifdef STATIC_LINK
	/** A function pointer to the factory function
	 */
	initfunc *factory_func;
#else
	/** A function pointer to the factory function
	 */
	void * (*factory_func)(void);	
#endif
};

/** This is the highest-level class of the DLLFactory system used to load InspIRCd modules.
 * Its job is to finally call the init_module function and obtain a pointer to a ModuleFactory.
 * This template is a container for ModuleFactory itself, so that it may 'plug' into ModuleFactory
 * and provide module loading capabilities transparently.
 */
template <class T> class DLLFactory : public DLLFactoryBase
{
 public:
	/** Default constructor.
	 * This constructor passes its paramerers down through DLLFactoryBase and then DLLManager
	 * to load the module, then calls the factory function to retrieve a pointer to a ModuleFactory
	 * class. It is then down to the core to call the ModuleFactory::CreateModule() method and
	 * receive a Module* which it can insert into its module lists.
	 */
	DLLFactory(InspIRCd* Instance, const char *fname, const char *func_name=0) : DLLFactoryBase(Instance, fname, func_name)
	{
		if (factory_func)
			factory = reinterpret_cast<T*>(factory_func());
		else
			factory = reinterpret_cast<T*>(-1);
	}
	
	/** The destructor deletes the ModuleFactory pointer.
	 */
	~DLLFactory()
	{
		if (factory)
			delete factory;
	}

	/** The ModuleFactory pointer.
	 */
	T *factory;
};

#endif