CppCMS
plugin.h
1 //
3 // Copyright (C) 2008-2016 Artyom Beilis (Tonkikh) <artyomtnk@yahoo.com>
4 //
5 // See accompanying file COPYING.TXT file for licensing details.
6 //
8 #ifndef CPPCMS_PLUGIN_H
9 #define CPPCMS_PLUGIN_H
10 #include <cppcms/defs.h>
11 #include <cppcms/cppcms_error.h>
12 #include <booster/callback.h>
13 #include <booster/hold_ptr.h>
14 #include <string>
15 #include <set>
16 
17 namespace booster { class shared_object; }
18 
19 namespace cppcms {
20 namespace json { class value; }
25 namespace plugin {
26 
31 class CPPCMS_API signature_error : public booster::bad_cast {
32 public:
33  signature_error(std::string const &msg);
34  ~signature_error() throw();
35  virtual char const *what() const throw();
36 private:
37  std::string msg_;
38 };
39 
40 
56 class CPPCMS_API scope {
57  scope(scope const &);
58  void operator=(scope const &);
59 public:
63  scope();
67  ~scope();
68 
72  scope(int argc,char **argv);
76  scope(json::value const &value);
77 
82  void paths(std::vector<std::string> const &paths);
89  void shared_object_pattern(std::string const &pattern);
90 
98  void load(std::string const &module);
99 
103  static bool is_loaded(std::string const &module);
104 
108  booster::shared_object const &get(std::string const &module) const;
109 
113  bool is_loaded_by_this_scope(std::string const &module) const;
114 private:
115  void init(json::value const &config);
116  struct _class_data;
117  static _class_data &class_data();
118 
119  struct _data;
121 };
122 
123 
134 class CPPCMS_API manager {
135 public:
139  static manager &instance();
140 
145  typedef refcounted_ptr (*entry_point_type)();
146 
167  template<typename Signature>
169  entry(std::string const &plugin_name,std::string const &entry_name)
170  {
171  typedef booster::callback<Signature> callback_type;
172  typedef typename callback_type::callable_type callable_type;
173  typedef typename callback_type::pointer_type pointer_type;
174 
175  entry_point_type plugin_call = instance().get_entry(plugin_name,entry_name);
176  if(!plugin_call)
177  throw cppcms_error("Could not find entry `" + entry_name + "' in plugin `" + plugin_name + "'");
178  refcounted_ptr call = plugin_call();
179  if(!call)
180  throw cppcms_error("Failed to create callback from plugin `"+plugin_name+"':entry `" + entry_name + "'");
181 
182  callable_type *real_call = dynamic_cast<callable_type *>(call.get());
183  if(!real_call) {
184  throw signature_error("Invalid signature request in plugin `"+ plugin_name +"':entry `"+entry_name+"', expected following signaure `" + instance().signature(plugin_name,entry_name) + "'");
185  }
186  pointer_type ptr(real_call);
187  callback_type result(ptr);
188  return result;
189  }
190 
194  template<typename Signature>
195  bool has_entry(std::string const &plugin,std::string const &name)
196  {
197  typedef booster::callback<Signature> callback_type;
198 
199  entry_point_type plugin_call = get_entry(plugin,name);
200  if(!plugin_call)
201  return false;
202  return dynamic_cast<callback_type *>(plugin_call().get())!=0;
203  }
204 
208  entry_point_type get_entry(std::string const &plugin,std::string const &name);
212  std::string signature(std::string const &plugin,std::string const &name);
213 
217  void add_entry(char const *plugin_name,char const *entry_name,entry_point_type entry,char const *signature);
221  void remove_entry(entry_point_type entry);
222 
226  std::set<std::string> plugins();
230  std::set<std::string> entries(std::string const &plugin);
231 
235  bool has_plugin(std::string const &name);
236 
237 private:
238  manager();
239  ~manager();
240  manager(manager const &);
241  void operator=(manager const &);
242 
243  struct _data;
244  struct entry_type;
246 };
247 
248 #define CPPCMS_PLUGIN_CONCAT(x,y) x ## y
249 #define CPPCMS_PLUGIN_CONCAT2(x,y) CPPCMS_PLUGIN_CONCAT(x,y)
250 
271 #define CPPCMS_FULL_PLUGIN_ENTRY(plugin_name,entry_name,call,type) \
272 namespace { \
273  struct CPPCMS_PLUGIN_CONCAT2(stpg_ , __LINE__) { \
274  static booster::intrusive_ptr<booster::refcounted> entry() \
275  { \
276  typedef booster::callback<type> ct; \
277  ct cb = call; \
278  booster::refcounted *tmp = cb.get_pointer().get(); \
279  booster::intrusive_ptr<booster::refcounted> ptr(tmp); \
280  return ptr; \
281  } \
282  CPPCMS_PLUGIN_CONCAT2(stpg_,__LINE__) () { \
283  cppcms::plugin::manager::instance().add_entry( \
284  plugin_name,entry_name,&entry,#type \
285  ); \
286  \
287  } \
288  ~CPPCMS_PLUGIN_CONCAT2(stpg_,__LINE__)() { \
289  cppcms::plugin::manager::instance().remove_entry(&entry); \
290  } \
291  } CPPCMS_PLUGIN_CONCAT2(instance_of_stpg_,__LINE__); \
292 }
293 
294 
317 #define CPPCMS_PLUGIN_ENTRY(name,call,type) CPPCMS_FULL_PLUGIN_ENTRY(#name,#call,& name :: call,type)
318 
341 #define CPPCMS_NAMED_PLUGIN_ENTRY(name,entry,call,type) CPPCMS_FULL_PLUGIN_ENTRY(#name,#entry,& name :: call,type)
342 
343 
344 } // plugin
345 } // cppcms
346 
347 #endif
Definition: plugin.h:134
This class is central representation of json objects.
Definition: json.h:140
Definition: plugin.h:31
Definition: callback.h:18
Exception thrown by CppCMS framework.
Definition: cppcms_error.h:22
Class that allows loading dynamic libraries: shared objects and dlls.
Definition: shared_object.h:22
This is the namespace where all CppCMS functionality is placed.
Definition: application.h:19
bool has_entry(std::string const &plugin, std::string const &name)
Definition: plugin.h:195
Definition: plugin.h:56
intrusive_ptr is the class taken as-is from boost.
Definition: intrusive_ptr.h:42
Same as std::bad_cast but records stack trace.
Definition: backtrace.h:151
booster::callback< Signature > entry(std::string const &plugin_name, std::string const &entry_name)
Definition: plugin.h:169
entry_point_type get_entry(std::string const &plugin, std::string const &name)
Booster library namespace. The library that implements Boost Like API in ABI backward compatible way...
Definition: application.h:23