pion-net
4.0.9
|
00001 // ----------------------------------------------------------------------- 00002 // pion-common: a collection of common libraries used by the Pion Platform 00003 // ----------------------------------------------------------------------- 00004 // Copyright (C) 2007-2008 Atomic Labs, Inc. (http://www.atomiclabs.com) 00005 // 00006 // Distributed under the Boost Software License, Version 1.0. 00007 // See http://www.boost.org/LICENSE_1_0.txt 00008 // 00009 00010 #ifndef __PION_PIONPLUGIN_HEADER__ 00011 #define __PION_PIONPLUGIN_HEADER__ 00012 00013 #include <vector> 00014 #include <string> 00015 #include <map> 00016 #include <list> 00017 #include <boost/thread/mutex.hpp> 00018 #include <boost/filesystem/path.hpp> 00019 #include <pion/PionConfig.hpp> 00020 #include <pion/PionException.hpp> 00021 00022 00023 namespace pion { // begin namespace pion 00024 00028 class PION_COMMON_API PionPlugin { 00029 public: 00030 00032 class PluginUndefinedException : public std::exception { 00033 public: 00034 virtual const char* what() const throw() { 00035 return "Plug-in was not loaded properly"; 00036 } 00037 }; 00038 00040 class DirectoryNotFoundException : public PionException { 00041 public: 00042 DirectoryNotFoundException(const std::string& dir) 00043 : PionException("Plug-in directory not found: ", dir) {} 00044 }; 00045 00047 class PluginNotFoundException : public PionException { 00048 public: 00049 PluginNotFoundException(const std::string& file) 00050 : PionException("Plug-in library not found: ", file) {} 00051 }; 00052 00054 class OpenPluginException : public PionException { 00055 public: 00056 OpenPluginException(const std::string& file) 00057 : PionException("Unable to open plug-in library: ", file) {} 00058 }; 00059 00061 class PluginMissingCreateException : public PionException { 00062 public: 00063 PluginMissingCreateException(const std::string& file) 00064 : PionException("Plug-in library does not include create() symbol: ", file) {} 00065 }; 00066 00068 class PluginMissingDestroyException : public PionException { 00069 public: 00070 PluginMissingDestroyException(const std::string& file) 00071 : PionException("Plug-in library does not include destroy() symbol: ", file) {} 00072 }; 00073 00081 static inline bool findPluginFile(std::string& path_to_file, 00082 const std::string& name) 00083 { 00084 return findFile(path_to_file, name, PION_PLUGIN_EXTENSION); 00085 } 00086 00094 static inline bool findConfigFile(std::string& path_to_file, 00095 const std::string& name) 00096 { 00097 return findFile(path_to_file, name, PION_CONFIG_EXTENSION); 00098 } 00099 00107 static bool findStaticEntryPoint(const std::string& plugin_name, 00108 void **create_func, 00109 void **destroy_func); 00110 00118 static void addStaticEntryPoint(const std::string& plugin_name, 00119 void *create_func, 00120 void *destroy_func); 00121 00130 static void checkCygwinPath(boost::filesystem::path& final_path, 00131 const std::string& path_string); 00132 00134 static void addPluginDirectory(const std::string& dir); 00135 00137 static void resetPluginDirectories(void); 00138 00139 00140 // default destructor 00141 virtual ~PionPlugin() { releaseData(); } 00142 00144 inline bool is_open(void) const { return (m_plugin_data != NULL); } 00145 00147 inline std::string getPluginName(void) const { 00148 return (is_open() ? m_plugin_data->m_plugin_name : std::string()); 00149 } 00150 00152 static void getAllPluginNames(std::vector<std::string>& plugin_names); 00153 00166 void open(const std::string& plugin_name); 00167 00180 void openFile(const std::string& plugin_file); 00181 00190 void openStaticLinked(const std::string& plugin_name, 00191 void *create_func, 00192 void *destroy_func); 00193 00195 inline void close(void) { releaseData(); } 00196 00197 protected: 00198 00202 struct PionPluginData 00203 { 00205 PionPluginData(void) 00206 : m_lib_handle(NULL), m_create_func(NULL), m_destroy_func(NULL), 00207 m_references(0) 00208 {} 00209 PionPluginData(const std::string& plugin_name) 00210 : m_lib_handle(NULL), m_create_func(NULL), m_destroy_func(NULL), 00211 m_plugin_name(plugin_name), m_references(0) 00212 {} 00213 PionPluginData(const PionPluginData& p) 00214 : m_lib_handle(p.m_lib_handle), m_create_func(p.m_create_func), 00215 m_destroy_func(p.m_destroy_func), m_plugin_name(p.m_plugin_name), 00216 m_references(p.m_references) 00217 {} 00218 00220 void * m_lib_handle; 00221 00223 void * m_create_func; 00224 00226 void * m_destroy_func; 00227 00229 std::string m_plugin_name; 00230 00232 unsigned long m_references; 00233 }; 00234 00235 00237 PionPlugin(void) : m_plugin_data(NULL) {} 00238 00240 PionPlugin(const PionPlugin& p) : m_plugin_data(NULL) { grabData(p); } 00241 00243 PionPlugin& operator=(const PionPlugin& p) { grabData(p); return *this; } 00244 00246 inline void *getCreateFunction(void) { 00247 return (is_open() ? m_plugin_data->m_create_func : NULL); 00248 } 00249 00251 inline void *getDestroyFunction(void) { 00252 return (is_open() ? m_plugin_data->m_destroy_func : NULL); 00253 } 00254 00256 void releaseData(void); 00257 00259 void grabData(const PionPlugin& p); 00260 00261 00262 private: 00263 00265 class StaticEntryPoint 00266 { 00267 public: 00268 StaticEntryPoint(const std::string& name, void *create, void *destroy) 00269 : m_plugin_name(name), m_create_func(create), m_destroy_func(destroy) 00270 {} 00271 std::string m_plugin_name; 00272 void * m_create_func; 00273 void * m_destroy_func; 00274 }; 00275 00277 typedef std::list<StaticEntryPoint> StaticEntryPointList; 00278 00280 typedef std::map<std::string, PionPluginData*> PluginMap; 00281 00282 00292 static bool findFile(std::string& path_to_file, const std::string& name, 00293 const std::string& extension); 00294 00305 static bool checkForFile(std::string& final_path, const std::string& start_path, 00306 const std::string& name, const std::string& extension); 00307 00314 static void openPlugin(const std::string& plugin_file, 00315 PionPluginData& plugin_data); 00316 00318 static std::string getPluginName(const std::string& plugin_file); 00319 00321 static void *loadDynamicLibrary(const std::string& plugin_file); 00322 00324 static void closeDynamicLibrary(void *lib_handle); 00325 00327 static void *getLibrarySymbol(void *lib_handle, const std::string& symbol); 00328 00329 00331 static const std::string PION_PLUGIN_CREATE; 00332 00334 static const std::string PION_PLUGIN_DESTROY; 00335 00337 static const std::string PION_PLUGIN_EXTENSION; 00338 00340 static const std::string PION_CONFIG_EXTENSION; 00341 00343 static std::vector<std::string> m_plugin_dirs; 00344 00346 static PluginMap m_plugin_map; 00347 00349 static boost::mutex m_plugin_mutex; 00350 00352 static StaticEntryPointList *m_entry_points_ptr; 00353 00355 PionPluginData * m_plugin_data; 00356 }; 00357 00358 00363 template <typename InterfaceClassType> 00364 class PionPluginPtr : 00365 public PionPlugin 00366 { 00367 protected: 00368 00370 typedef InterfaceClassType* CreateObjectFunction(void); 00371 00373 typedef void DestroyObjectFunction(InterfaceClassType*); 00374 00375 00376 public: 00377 00379 PionPluginPtr(void) : PionPlugin() {} 00380 virtual ~PionPluginPtr() {} 00381 00383 PionPluginPtr(const PionPluginPtr& p) : PionPlugin(p) {} 00384 00386 PionPluginPtr& operator=(const PionPluginPtr& p) { grabData(p); return *this; } 00387 00389 inline InterfaceClassType *create(void) { 00390 CreateObjectFunction *create_func = 00391 (CreateObjectFunction*)(getCreateFunction()); 00392 if (create_func == NULL) 00393 throw PluginUndefinedException(); 00394 return create_func(); 00395 } 00396 00398 inline void destroy(InterfaceClassType *object_ptr) { 00399 DestroyObjectFunction *destroy_func = 00400 (DestroyObjectFunction*)(getDestroyFunction()); 00401 if (destroy_func == NULL) 00402 throw PluginUndefinedException(); 00403 destroy_func(object_ptr); 00404 } 00405 }; 00406 00407 00421 #ifdef PION_STATIC_LINKING 00422 00423 #define PION_DECLARE_PLUGIN(plugin_name) \ 00424 class plugin_name; \ 00425 extern "C" plugin_name *pion_create_##plugin_name(void); \ 00426 extern "C" void pion_destroy_##plugin_name(plugin_name *plugin_ptr); \ 00427 static pion::StaticEntryPointHelper helper_##plugin_name(#plugin_name, pion_create_##plugin_name, pion_destroy_##plugin_name); 00428 00430 class StaticEntryPointHelper { 00431 public: 00432 StaticEntryPointHelper(const std::string& name, void *create, void *destroy) 00433 { 00434 pion::PionPlugin::addStaticEntryPoint(name, create, destroy); 00435 } 00436 }; 00437 00438 #else 00439 00440 #define PION_DECLARE_PLUGIN(plugin_name) 00441 00442 #endif 00443 00444 } // end namespace pion 00445 00446 #endif