00001
00002
00003
00004
00005
00006
00007
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 {
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
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 }
00445
00446 #endif