# common/include/pion/PionPlugin.hpp

    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