00001
00002
00003
00004
00005
00006
00007
00008
00009
00010 #ifndef __PION_PLUGIN_HEADER__
00011 #define __PION_PLUGIN_HEADER__
00012
00013 #include <vector>
00014 #include <string>
00015 #include <map>
00016 #include <list>
00017 #include <boost/noncopyable.hpp>
00018 #include <boost/thread/once.hpp>
00019 #include <boost/thread/mutex.hpp>
00020 #include <boost/filesystem/path.hpp>
00021 #include <pion/config.hpp>
00022 #include <pion/error.hpp>
00023
00024
00025 namespace pion {
00026
00030 class PION_API plugin {
00031 public:
00032
00040 static inline bool find_plugin_file(std::string& path_to_file,
00041 const std::string& name)
00042 {
00043 return find_file(path_to_file, name, PION_PLUGIN_EXTENSION);
00044 }
00045
00053 static inline bool find_config_file(std::string& path_to_file,
00054 const std::string& name)
00055 {
00056 return find_file(path_to_file, name, PION_CONFIG_EXTENSION);
00057 }
00058
00067 static void add_static_entry_point(const std::string& plugin_name,
00068 void *create_func,
00069 void *destroy_func);
00070
00079 static void check_cygwin_path(boost::filesystem::path& final_path,
00080 const std::string& path_string);
00081
00083 static void add_plugin_directory(const std::string& dir);
00084
00086 static void reset_plugin_directories(void);
00087
00088
00089
00090 virtual ~plugin() { release_data(); }
00091
00093 inline bool is_open(void) const { return (m_plugin_data != NULL); }
00094
00096 inline std::string get_plugin_name(void) const {
00097 return (is_open() ? m_plugin_data->m_plugin_name : std::string());
00098 }
00099
00101 static void get_all_plugin_names(std::vector<std::string>& plugin_names);
00102
00115 void open(const std::string& plugin_name);
00116
00129 void open_file(const std::string& plugin_file);
00130
00132 inline void close(void) { release_data(); }
00133
00134 protected:
00135
00139 struct data_type
00140 {
00142 data_type(void)
00143 : m_lib_handle(NULL), m_create_func(NULL), m_destroy_func(NULL),
00144 m_references(0)
00145 {}
00146 data_type(const std::string& plugin_name)
00147 : m_lib_handle(NULL), m_create_func(NULL), m_destroy_func(NULL),
00148 m_plugin_name(plugin_name), m_references(0)
00149 {}
00150 data_type(const data_type& p)
00151 : m_lib_handle(p.m_lib_handle), m_create_func(p.m_create_func),
00152 m_destroy_func(p.m_destroy_func), m_plugin_name(p.m_plugin_name),
00153 m_references(p.m_references)
00154 {}
00155
00157 void * m_lib_handle;
00158
00160 void * m_create_func;
00161
00163 void * m_destroy_func;
00164
00166 std::string m_plugin_name;
00167
00169 unsigned long m_references;
00170 };
00171
00172
00174 plugin(void) : m_plugin_data(NULL) {}
00175
00177 plugin(const plugin& p) : m_plugin_data(NULL) { grab_data(p); }
00178
00180 plugin& operator=(const plugin& p) { grab_data(p); return *this; }
00181
00183 inline void *get_create_function(void) {
00184 return (is_open() ? m_plugin_data->m_create_func : NULL);
00185 }
00186
00188 inline void *get_destroy_function(void) {
00189 return (is_open() ? m_plugin_data->m_destroy_func : NULL);
00190 }
00191
00193 void release_data(void);
00194
00196 void grab_data(const plugin& p);
00197
00198
00199 private:
00200
00202 typedef std::map<std::string, data_type*> map_type;
00203
00205 struct config_type {
00207 std::vector<std::string> m_plugin_dirs;
00208
00210 map_type m_plugin_map;
00211
00213 boost::mutex m_plugin_mutex;
00214 };
00215
00216
00218 static inline config_type& get_plugin_config(void) {
00219 boost::call_once(plugin::create_plugin_config, m_instance_flag);
00220 return *m_config_ptr;
00221 }
00222
00224 static void create_plugin_config(void);
00225
00235 static bool find_file(std::string& path_to_file, const std::string& name,
00236 const std::string& extension);
00237
00248 static bool check_for_file(std::string& final_path, const std::string& start_path,
00249 const std::string& name, const std::string& extension);
00250
00257 static void open_plugin(const std::string& plugin_file,
00258 data_type& plugin_data);
00259
00261 static std::string get_plugin_name(const std::string& plugin_file);
00262
00264 static void *load_dynamic_library(const std::string& plugin_file);
00265
00267 static void close_dynamic_library(void *lib_handle);
00268
00270 static void *get_library_symbol(void *lib_handle, const std::string& symbol);
00271
00272
00274 static const std::string PION_PLUGIN_CREATE;
00275
00277 static const std::string PION_PLUGIN_DESTROY;
00278
00280 static const std::string PION_PLUGIN_EXTENSION;
00281
00283 static const std::string PION_CONFIG_EXTENSION;
00284
00286 static boost::once_flag m_instance_flag;
00287
00289 static config_type * m_config_ptr;
00290
00292 data_type * m_plugin_data;
00293 };
00294
00295
00300 template <typename InterfaceClassType>
00301 class plugin_ptr :
00302 public plugin
00303 {
00304 protected:
00305
00307 typedef InterfaceClassType* CreateObjectFunction(void);
00308
00310 typedef void DestroyObjectFunction(InterfaceClassType*);
00311
00312
00313 public:
00314
00316 plugin_ptr(void) : plugin() {}
00317 virtual ~plugin_ptr() {}
00318
00320 plugin_ptr(const plugin_ptr& p) : plugin(p) {}
00321
00323 plugin_ptr& operator=(const plugin_ptr& p) { grab_data(p); return *this; }
00324
00326 inline InterfaceClassType *create(void) {
00327 CreateObjectFunction *create_func =
00328 (CreateObjectFunction*)(get_create_function());
00329 if (create_func == NULL)
00330 BOOST_THROW_EXCEPTION( error::plugin_undefined() );
00331 return create_func();
00332 }
00333
00335 inline void destroy(InterfaceClassType *object_ptr) {
00336
00337
00338 union {
00339 void* v_;
00340 DestroyObjectFunction* f_;
00341 } Cast;
00342 Cast.v_ = get_destroy_function();
00343 DestroyObjectFunction *destroy_func = Cast.f_;
00344 if (destroy_func == NULL)
00345 BOOST_THROW_EXCEPTION( error::plugin_undefined() );
00346 destroy_func(object_ptr);
00347 }
00348 };
00349
00350
00354 template <typename InterfaceClassType>
00355 class plugin_instance_ptr :
00356 private boost::noncopyable
00357 {
00358 public:
00359
00361 plugin_instance_ptr(void) : m_instance_ptr(NULL) {}
00362
00364 virtual ~plugin_instance_ptr() { reset(); }
00365
00367 inline void reset(void) {
00368 if (m_instance_ptr) {
00369 m_plugin_ptr.destroy(m_instance_ptr);
00370 }
00371 }
00372
00374 inline void create(const std::string& plugin_type) {
00375 reset();
00376 m_plugin_ptr.open(plugin_type);
00377 m_instance_ptr = m_plugin_ptr.create();
00378 }
00379
00381 inline bool empty(void) const { return m_instance_ptr==NULL; }
00382
00384 inline InterfaceClassType *get(void) { return m_instance_ptr; }
00385
00387 inline InterfaceClassType& operator*(void) { return *m_instance_ptr; }
00388
00390 inline const InterfaceClassType& operator*(void) const { return *m_instance_ptr; }
00391
00393 inline InterfaceClassType* operator->(void) { return m_instance_ptr; }
00394
00396 inline const InterfaceClassType* operator->(void) const { return m_instance_ptr; }
00397
00398
00399 protected:
00400
00402 plugin_ptr<InterfaceClassType> m_plugin_ptr;
00403
00405 InterfaceClassType * m_instance_ptr;
00406 };
00407
00408
00422 #ifdef PION_STATIC_LINKING
00423
00424 #define PION_DECLARE_PLUGIN(plugin_name) \
00425 class plugin_name; \
00426 extern "C" plugin_name *pion_create_##plugin_name(void); \
00427 extern "C" void pion_destroy_##plugin_name(plugin_name *plugin_ptr); \
00428 static pion::static_entry_point_helper helper_##plugin_name(#plugin_name, (void*) pion_create_##plugin_name, (void*) pion_destroy_##plugin_name);
00429
00431 class static_entry_point_helper {
00432 public:
00433 static_entry_point_helper(const std::string& name, void *create, void *destroy)
00434 {
00435 pion::plugin::add_static_entry_point(name, create, destroy);
00436 }
00437 };
00438
00439 #else
00440
00441 #define PION_DECLARE_PLUGIN(plugin_name)
00442
00443 #endif
00444
00445 }
00446
00447 #endif