2 Copyright (C) 2001-2006, William Joseph.
5 This file is part of GtkRadiant.
7 GtkRadiant is free software; you can redistribute it and/or modify
8 it under the terms of the GNU General Public License as published by
9 the Free Software Foundation; either version 2 of the License, or
10 (at your option) any later version.
12 GtkRadiant is distributed in the hope that it will be useful,
13 but WITHOUT ANY WARRANTY; without even the implied warranty of
14 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 GNU General Public License for more details.
17 You should have received a copy of the GNU General Public License
18 along with GtkRadiant; if not, write to the Free Software
19 Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
23 #include "globaldefs.h"
25 #include "debugging/debugging.h"
32 #include "modulesystem.h"
34 class RadiantModuleServer : public ModuleServer {
35 typedef std::pair<CopiedString, int> ModuleType;
36 typedef std::pair<ModuleType, CopiedString> ModuleKey;
37 typedef std::map<ModuleKey, Module *> Modules_;
42 RadiantModuleServer() : m_error(false)
46 void setError(bool error)
56 TextOutputStream &getOutputStream()
58 return globalOutputStream();
61 TextOutputStream &getErrorStream()
63 return globalErrorStream();
66 DebugMessageHandler &getDebugMessageHandler()
68 return globalDebugMessageHandler();
71 void registerModule(const char *type, int version, const char *name, Module &module)
73 if (!m_modules.insert(Modules_::value_type(ModuleKey(ModuleType(type, version), name), &module)).second) {
74 globalErrorStream() << "module already registered: type=" << makeQuoted(type) << " name="
75 << makeQuoted(name) << "\n";
77 globalOutputStream() << "Module Registered: type=" << makeQuoted(type) << " version=" << makeQuoted(version)
78 << " name=" << makeQuoted(name) << "\n";
82 Module *findModule(const char *type, int version, const char *name) const
84 Modules_::const_iterator i = m_modules.find(ModuleKey(ModuleType(type, version), name));
85 if (i != m_modules.end()) {
91 void foreachModule(const char *type, int version, const Visitor &visitor)
93 for (Modules_::const_iterator i = m_modules.begin(); i != m_modules.end(); ++i) {
94 if (string_equal((*i).first.first.first.c_str(), type)) {
95 visitor.visit((*i).first.second.c_str(), *(*i).second);
106 const int FORMAT_BUFSIZE = 2048;
107 const char* FormatGetLastError(){
108 static char buf[FORMAT_BUFSIZE];
110 FORMAT_MESSAGE_FROM_SYSTEM |
111 FORMAT_MESSAGE_IGNORE_INSERTS,
114 MAKELANGID( LANG_NEUTRAL, SUBLANG_DEFAULT ), // Default language
126 typedef int ( __stdcall * FunctionPointer )();
128 DynamicLibrary( const char* filename ){
129 m_library = LoadLibrary( filename );
130 if ( m_library == 0 ) {
131 globalErrorStream() << "LoadLibrary failed: '" << filename << "'\n";
132 globalErrorStream() << "GetLastError: " << FormatGetLastError();
137 FreeLibrary( m_library );
141 return m_library == 0;
143 FunctionPointer findSymbol( const char* symbol ){
144 FunctionPointer address = (FunctionPointer) GetProcAddress( m_library, symbol );
145 if ( address == 0 ) {
146 globalErrorStream() << "GetProcAddress failed: '" << symbol << "'\n";
147 globalErrorStream() << "GetLastError: " << FormatGetLastError();
157 class DynamicLibrary {
160 typedef int ( *FunctionPointer )();
162 DynamicLibrary(const char *filename)
164 m_library = dlopen(filename, RTLD_NOW);
176 return m_library == 0;
179 FunctionPointer findSymbol(const char *symbol)
181 FunctionPointer p = (FunctionPointer) dlsym(m_library, symbol);
183 const char *error = reinterpret_cast<const char *>( dlerror());
185 globalErrorStream() << error;
193 #error "unsupported platform"
196 class DynamicLibraryModule {
197 typedef void ( RADIANT_DLLIMPORT *RegisterModulesFunc )(ModuleServer &server);
199 DynamicLibrary m_library;
200 RegisterModulesFunc m_registerModule;
202 DynamicLibraryModule(const char *filename)
203 : m_library(filename), m_registerModule(0)
205 if (!m_library.failed()) {
206 m_registerModule = reinterpret_cast<RegisterModulesFunc>( m_library.findSymbol("Radiant_RegisterModules"));
208 if ( !m_registerModule ) {
209 m_registerModule = reinterpret_cast<RegisterModulesFunc>( m_library.findSymbol( "Radiant_RegisterModules@4" ) );
217 return m_registerModule == 0;
220 void registerModules(ModuleServer &server)
222 m_registerModule(server);
228 typedef std::vector<DynamicLibraryModule *> libraries_t;
229 libraries_t m_libraries;
237 void registerLibrary(const char *filename, ModuleServer &server)
239 DynamicLibraryModule *library = new DynamicLibraryModule(filename);
241 if (library->failed()) {
244 m_libraries.push_back(library);
245 library->registerModules(server);
251 for (libraries_t::iterator i = m_libraries.begin(); i != m_libraries.end(); ++i) {
263 Libraries g_libraries;
264 RadiantModuleServer g_server;
266 ModuleServer &GlobalModuleServer_get()
271 void GlobalModuleServer_loadModule(const char *filename)
273 g_libraries.registerLibrary(filename, g_server);
276 void GlobalModuleServer_Initialise()
280 void GlobalModuleServer_Shutdown()