libqi-api  2.4.3.28
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Pages
objecttypebuilder.hpp
Go to the documentation of this file.
1 #pragma once
2 /*
3 ** Copyright (C) 2013 Aldebaran Robotics
4 ** See COPYING for the license
5 */
6 
7 #ifndef _QI_TYPE_OBJECTTYPEBUILDER_HPP_
8 #define _QI_TYPE_OBJECTTYPEBUILDER_HPP_
9 
10 #include <qi/api.hpp>
11 #include <string>
12 
13 #include <boost/function.hpp>
14 #include <qi/signature.hpp>
15 #include <sstream>
20 #include <qi/property.hpp>
21 
22 namespace qi {
23 
24 namespace detail {
25  struct ObjectTypeData;
26 }
27 
28  class MetaObject;
29 
30  class SignalBase;
31  class ObjectTypeInterface;
32  class TypeInterface;
33  template<typename T> class SignalF;
34  class ObjectTypeBuilderPrivate;
35 
37  {
38  public:
41 
42  typedef boost::function<SignalBase* (void*)> SignalMemberGetter;
43  typedef boost::function<PropertyBase* (void*)> PropertyMemberGetter;
44 
46  void setDescription(const std::string& description);
47 
48  // input: template-based
49 
51  template<typename T> void buildFor(bool autoRegister = true);
52 
53  template <typename FUNCTION_TYPE>
54  inline unsigned int advertiseMethod(const std::string& name, FUNCTION_TYPE function, MetaCallType threadingModel = MetaCallType_Auto, int id = -1);
55 
56  template <typename FUNCTION_TYPE>
57  inline unsigned int advertiseMethod(MetaMethodBuilder& name, FUNCTION_TYPE function, MetaCallType threadingModel = MetaCallType_Auto, int id = -1);
58 
59  template<typename A>
60  unsigned int advertiseSignal(const std::string& eventName, A accessor, int id = -1);
61 
62  template <typename T>
63  inline unsigned int advertiseSignal(const std::string& name, SignalMemberGetter getter, int id = -1);
64 
65  template <typename A>
66  inline unsigned int advertiseProperty(const std::string& propertyName, A accessor);
67 
68  template<typename T>
69  inline unsigned int advertiseProperty(const std::string& eventName, PropertyMemberGetter getter);
70 
74  #define genCall(n, ATYPEDECL, ATYPES, ADECL, AUSE, comma) \
75  template<typename T comma ATYPEDECL> \
76  inline unsigned int advertiseFactory(const std::string& name) \
77  { \
78  return advertiseMethod(name, &constructObject<T comma ATYPES>); \
79  }
81  #undef genCall
82 
83  template<typename P>
84  void inherits(int offset);
85 
86  // Advertise anything, dispatch on {method, event, property} based on T.
87  template<typename T>
88  ObjectTypeBuilderBase& advertise(const std::string& name, T element);
89  // Like advertise, but return the id
90  template<typename T>
91  unsigned int advertiseId(const std::string& name, T element);
92  // input: type-erased
93 
94  unsigned int xAdvertiseMethod(MetaMethodBuilder& builder, AnyFunction func, MetaCallType threadingModel = MetaCallType_Auto, int id = -1);
95  unsigned int xAdvertiseSignal(const std::string &name, const qi::Signature& signature, SignalMemberGetter getter, int id = -1);
96  unsigned int xAdvertiseProperty(const std::string& name, const qi::Signature& signature, PropertyMemberGetter getter, int id = -1);
97  void xBuildFor(TypeInterface* type, bool autoRegister, qi::AnyFunction strandAccessor);
98  void inherits(TypeInterface* parentType, int offset);
99 
100  // Configuration
101 
102  void setThreadingModel(ObjectThreadingModel model);
103 
104  // output
105  const MetaObject& metaObject();
106  AnyObject object(void* ptr, boost::function<void (GenericObject*)> onDestroy = boost::function<void (GenericObject*)>());
107  ObjectTypeInterface* type();
108 
110  inline virtual void registerType() {};
111 
112  const detail::ObjectTypeData& typeData();
113  private:
114  ObjectTypeBuilderPrivate* _p;
115  };
116 
117  template<typename T>
119  {
120  public:
121  ObjectTypeBuilder(bool autoRegister=true)
122  {
123  buildFor<T>(autoRegister);
124  }
125 
131  template<typename U> void inherits();
132 
133  template <typename FUNCTION_TYPE>
134  inline unsigned int advertiseMethod(const std::string& name,
135  FUNCTION_TYPE function,
136  MetaCallType threadingModel = MetaCallType_Auto,
137  int id = -1);
138 
139  template <typename FUNCTION_TYPE>
140  inline unsigned int advertiseMethod(MetaMethodBuilder& name,
141  FUNCTION_TYPE function,
142  MetaCallType threadingModel = MetaCallType_Auto,
143  int id = -1);
144 
145 
147  inline virtual void registerType();
148 
149  inline AnyObject object(T* ptr, boost::function<void (GenericObject*)> onDestroy = boost::function<void (GenericObject*)>());
150  };
151 }
152 
154 
161 #define QI_OBJECT_BUILDER_ADVERTISE(builder, cls, name) \
162  builder.advertise(BOOST_PP_STRINGIZE(name), &cls::name)
163 
174 #define QI_OBJECT_BUILDER_ADVERTISE_OVERLOAD(builder, cls, name, ret, args) \
175  builder.advertiseMethod(BOOST_PP_STRINGIZE(name), static_cast<ret (cls::*)args>(&cls::name))
176 
177 #define __QI_REGISTER_ELEMENT(_, name, field) \
178  b.advertise(BOOST_PP_STRINGIZE(field), & name::field); // do not remove the space
179 
187 #define QI_REGISTER_OBJECT(name, ...) \
188  static bool _qiregister##name() { \
189  ::qi::ObjectTypeBuilder<name > b; \
190  QI_VAARGS_APPLY(__QI_REGISTER_ELEMENT, name, __VA_ARGS__) \
191  b.registerType(); \
192  return true; \
193  } \
194  static bool BOOST_PP_CAT(__qi_registration, __LINE__) = _qiregister##name();
195 
196 #define QI_REGISTER_MT_OBJECT(name, ...) \
197  static bool _qiregister##name() { \
198  ::qi::ObjectTypeBuilder<name > b; \
199  b.setThreadingModel(qi::ObjectThreadingModel_MultiThread); \
200  QI_VAARGS_APPLY(__QI_REGISTER_ELEMENT, name, __VA_ARGS__) \
201  b.registerType(); \
202  return true; \
203  } \
204  static bool BOOST_PP_CAT(__qi_registration, __LINE__) = _qiregister##name();
205 
212 #define QI_REGISTER_IMPLEMENTATION(parent, name) \
213  static bool _qiregister##name() \
214  { \
215  qi::registerType(typeid(name), qi::typeOf<parent>()); \
216  name* ptr = static_cast<name*>(reinterpret_cast<void*>(0x10000)); \
217  parent* pptr = ptr; \
218  intptr_t offset = reinterpret_cast<intptr_t>(pptr) - reinterpret_cast<intptr_t>(ptr); \
219  if (offset) \
220  { \
221  qiLogError("qitype.register") << "non-zero offset for implementation " << #name << " of " << #parent \
222  << ", call will fail at runtime"; \
223  throw std::runtime_error("non-zero offset between implementation and interface"); \
224  } \
225  return true; \
226  } \
227  static bool BOOST_PP_CAT(__qi_registration, __LINE__) = _qiregister##name();
228 
229 #define _QI_REGISTER_TEMPLATE_OBJECT(name, model, ...) \
230  namespace qi \
231  { \
232  template <> \
233  class QI_API TypeOfTemplate<name> : public detail::StaticObjectTypeBase \
234  { \
235  public: \
236  virtual TypeInterface* templateArgument() = 0; \
237  }; \
238  template <typename T> \
239  class TypeOfTemplateImpl<name, T> : public TypeOfTemplate<name> \
240  { \
241  public: \
242  TypeOfTemplateImpl() \
243  { \
244  /* early self registering to avoid recursive init */ \
245  ::qi::registerType(typeid(name<T>), this); \
246  ObjectTypeBuilder<name<T> > b(false); \
247  b.setThreadingModel(model); \
248  QI_VAARGS_APPLY(__QI_REGISTER_ELEMENT, name<T>, __VA_ARGS__) \
249  this->initialize(b.metaObject(), b.typeData()); \
250  } \
251  virtual TypeInterface* templateArgument() { return typeOf<T>(); } \
252  typedef DefaultTypeImplMethods<name<T> > Methods; \
253  _QI_BOUNCE_TYPE_METHODS(Methods); \
254  }; \
255  } \
256  QI_TEMPLATE_TYPE_DECLARE(name)
257 
262 #define QI_TEMPLATE_OBJECT(name, ...) \
263  _QI_REGISTER_TEMPLATE_OBJECT(name, ObjectThreadingModel_SingleThread, \
264  __VA_ARGS__)
265 
268 #define QI_REGISTER_TEMPLATE_OBJECT(name, ...) \
269  QI_TEMPLATE_OBJECT(name, __VA_ARGS__)
270 
273 #define QI_MT_TEMPLATE_OBJECT(name, ...) \
274  _QI_REGISTER_TEMPLATE_OBJECT(name, ObjectThreadingModel_MultiThread, \
275  __VA_ARGS__)
276 
277 QI_MT_TEMPLATE_OBJECT(qi::Future, _connect, isFinished, value, waitFor, waitUntil, isRunning, isCanceled, hasError, error, cancel);
278 QI_MT_TEMPLATE_OBJECT(qi::FutureSync, _connect, isFinished, value, waitFor, waitUntil, isRunning, isCanceled, hasError, error, async, cancel);
279 QI_MT_TEMPLATE_OBJECT(qi::Promise, setValue, setError, setCanceled, future, value, trigger);
280 
281 namespace qi { namespace detail {
282  template<typename T> struct TypeManager<Future<T> >: public TypeManagerDefaultStruct<Future<T> > {};
283  template<typename T> struct TypeManager<FutureSync<T> >: public TypeManagerDefaultStruct<FutureSync<T> > {};
284  template<typename T> struct TypeManager<Promise<T> >: public TypeManagerDefaultStruct<Promise<T> > {};
285 }}
286 
287 #endif // _QITYPE_OBJECTTYPEBUILDER_HPP_
#define QI_API
Definition: api.hpp:34
AnyObject object(T *ptr, boost::function< void(GenericObject *)> onDestroy=boost::function< void(GenericObject *)>())
Honor the default behavior.
Definition: typeobject.hpp:21
virtual void registerType()
Register type to typeof. Called by type()
dll import/export and compiler message
virtual void registerType()
Register type to typeOf<T>, to avoid both TypeImpl<T> and type() being present.
boost::function< SignalBase *(void *)> SignalMemberGetter
Future< R > async(boost::function< R()> callback, uint64_t usDelay=0)
Definition: eventloop.hpp:176
ObjectTypeBuilder(bool autoRegister=true)
#define QI_MT_TEMPLATE_OBJECT(name,...)
boost::function< PropertyBase *(void *)> PropertyMemberGetter
#define genCall(n, ATYPEDECL, ATYPES, ADECL, AUSE, comma)
MetaCallType
Definition: typeobject.hpp:19
Object< Empty > AnyObject
Definition: anyobject.hpp:21
unsigned int advertiseMethod(const std::string &name, FUNCTION_TYPE function, MetaCallType threadingModel=MetaCallType_Auto, int id=-1)
unsigned int advertise(ObjectTypeBuilderBase *builder, const std::string &name, A accessor, Dummy< 0 >)
ObjectThreadingModel
Possible thread models for an object.
Definition: manageable.hpp:30
#define QI_GEN(f)
Definition: preproc.hpp:476