libqi-api  2.8.7.4
 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  using SignalMemberGetter = boost::function<SignalBase* (void*)>;
43  using PropertyMemberGetter = boost::function<PropertyBase* (void*)>;
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, bool isSignalProperty = false);
61 
62  template <typename T>
63  inline unsigned int advertiseSignal(const std::string& name, SignalMemberGetter getter, int id = -1, bool isSignalProperty = false);
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  template<typename T, typename... Args>
75  inline unsigned int advertiseFactory(const std::string& name)
76  {
77  return advertiseMethod(name, &constructObject<T, Args...>);
78  }
79 
80  template<typename P>
81  void inherits(std::ptrdiff_t offset);
82 
83  // Advertise anything, dispatch on {method, event, property} based on T.
84  template<typename T>
85  ObjectTypeBuilderBase& advertise(const std::string& name, T element);
86  // Like advertise, but return the id
87  template<typename T>
88  unsigned int advertiseId(const std::string& name, T element);
89  // input: type-erased
90 
91  unsigned int xAdvertiseMethod(MetaMethodBuilder& builder, AnyFunction func, MetaCallType threadingModel = MetaCallType_Auto, int id = -1);
92  unsigned int xAdvertiseSignal(const std::string &name, const qi::Signature& signature, SignalMemberGetter getter, int id = -1, bool isSignalProperty = false);
93  unsigned int xAdvertiseProperty(const std::string& name, const qi::Signature& signature, PropertyMemberGetter getter, int id = -1);
94  void xBuildFor(TypeInterface* type, bool autoRegister, qi::AnyFunction strandAccessor);
95  void inherits(TypeInterface* parentType, std::ptrdiff_t offset);
96 
97  // Configuration
98 
99  void setThreadingModel(ObjectThreadingModel model);
100 
101  // output
102  const MetaObject& metaObject();
103  AnyObject object(void* ptr, boost::function<void (GenericObject*)> onDestroy = boost::function<void (GenericObject*)>());
104  ObjectTypeInterface* type();
105 
107  inline virtual void registerType() {};
108 
109  const detail::ObjectTypeData& typeData();
110  private:
111  ObjectTypeBuilderPrivate* _p;
112  };
113 
114  template<typename T>
116  {
117  public:
118  ObjectTypeBuilder(bool autoRegister=true)
119  {
120  buildFor<T>(autoRegister);
121  }
122 
128  template<typename U> void inherits();
129 
130  template <typename FUNCTION_TYPE>
131  inline unsigned int advertiseMethod(const std::string& name,
132  FUNCTION_TYPE function,
133  MetaCallType threadingModel = MetaCallType_Auto,
134  int id = -1);
135 
136  template <typename FUNCTION_TYPE>
137  inline unsigned int advertiseMethod(MetaMethodBuilder& name,
138  FUNCTION_TYPE function,
139  MetaCallType threadingModel = MetaCallType_Auto,
140  int id = -1);
141 
142 
144  inline virtual void registerType();
145 
146  inline AnyObject object(T* ptr, boost::function<void (GenericObject*)> onDestroy = boost::function<void (GenericObject*)>());
147  };
148 }
149 
151 
158 #define QI_OBJECT_BUILDER_ADVERTISE(builder, cls, name) \
159  builder.advertise(BOOST_PP_STRINGIZE(name), &cls::name)
160 
171 #define QI_OBJECT_BUILDER_ADVERTISE_OVERLOAD(builder, cls, name, ret, args) \
172  builder.advertiseMethod(BOOST_PP_STRINGIZE(name), static_cast<ret (cls::*)args>(&cls::name))
173 
174 #define __QI_REGISTER_ELEMENT(_, name, field) \
175  b.advertise(BOOST_PP_STRINGIZE(field), & name::field); // do not remove the space
176 
184 #define QI_REGISTER_OBJECT(name, ...) \
185 static bool BOOST_PP_CAT(__qi_registration, __LINE__) QI_ATTR_UNUSED = [] \
186 { \
187  ::qi::ObjectTypeBuilder<name> b; \
188  QI_VAARGS_APPLY(__QI_REGISTER_ELEMENT, name, __VA_ARGS__) \
189  b.registerType(); \
190  return true; \
191 }();
192 
193 #define QI_REGISTER_MT_OBJECT(name, ...) \
194 static bool BOOST_PP_CAT(__qi_registration, __LINE__) QI_ATTR_UNUSED = [] \
195 { \
196  ::qi::ObjectTypeBuilder<name> b; \
197  b.setThreadingModel(qi::ObjectThreadingModel_MultiThread); \
198  QI_VAARGS_APPLY(__QI_REGISTER_ELEMENT, name, __VA_ARGS__) \
199  b.registerType(); \
200  return true; \
201 }();
202 
209 #define QI_REGISTER_IMPLEMENTATION(parent, name) \
210  static bool BOOST_PP_CAT(__qi_registration_func, __LINE__)() \
211  { \
212  qi::detail::ForceProxyInclusion<parent>().dummyCall(); \
213  qi::registerType(qi::typeId<name>(), qi::typeOf<parent>()); \
214  name* ptr = static_cast<name*>(reinterpret_cast<void*>(0x10000)); \
215  parent* pptr = ptr; \
216  intptr_t offset = reinterpret_cast<intptr_t>(pptr) - reinterpret_cast<intptr_t>(ptr); \
217  if (offset) \
218  { \
219  qiLogError("qitype.register") << "non-zero offset for implementation " << #name << " of " << #parent \
220  << ", call will fail at runtime"; \
221  throw std::runtime_error("non-zero offset between implementation and interface"); \
222  } \
223  return true; \
224  } \
225  static bool BOOST_PP_CAT(__qi_registration, __LINE__) = BOOST_PP_CAT(__qi_registration_func, __LINE__)();
226 
227 #define _QI_REGISTER_TEMPLATE_OBJECT(name, model, ...) \
228  namespace qi \
229  { \
230  template <> \
231  class QI_API TypeOfTemplate<name> : public detail::StaticObjectTypeBase \
232  { \
233  public: \
234  virtual TypeInterface* templateArgument() = 0; \
235  }; \
236  template <typename T> \
237  class TypeOfTemplateImpl<name, T> : public TypeOfTemplate<name> \
238  { \
239  public: \
240  TypeOfTemplateImpl() \
241  { \
242  /* early self registering to avoid recursive init */ \
243  ::qi::registerType(qi::typeId<name<T>>(), this); \
244  ObjectTypeBuilder<name<T> > b(false); \
245  b.setThreadingModel(model); \
246  QI_VAARGS_APPLY(__QI_REGISTER_ELEMENT, name<T>, __VA_ARGS__) \
247  this->initialize(b.metaObject(), b.typeData()); \
248  } \
249  TypeInterface* templateArgument() override { return typeOf<T>(); } \
250  using Methods = DefaultTypeImplMethods<name<T>>; \
251  _QI_BOUNCE_TYPE_METHODS(Methods); \
252  }; \
253  } \
254  QI_TEMPLATE_TYPE_DECLARE(name)
255 
260 #define QI_TEMPLATE_OBJECT(name, ...) \
261  _QI_REGISTER_TEMPLATE_OBJECT(name, ObjectThreadingModel_SingleThread, \
262  __VA_ARGS__)
263 
266 #define QI_REGISTER_TEMPLATE_OBJECT(name, ...) \
267  QI_TEMPLATE_OBJECT(name, __VA_ARGS__)
268 
271 #define QI_MT_TEMPLATE_OBJECT(name, ...) \
272  _QI_REGISTER_TEMPLATE_OBJECT(name, ObjectThreadingModel_MultiThread, \
273  __VA_ARGS__)
274 
275 // sometimes we need to use type-erased futures, but only those two methods are needed, so register our futures as
276 // normal objects with these methods
277 namespace qi
278 {
279 template <>
281 {
282 public:
283  virtual TypeInterface* templateArgument() = 0;
284 };
285 template <>
287 {
288 public:
289  virtual TypeInterface* templateArgument() = 0;
290 };
291 template <template<typename> class FutT, typename T>
293 {
294 public:
296  {
297  /* early self registering to avoid recursive init */
298  ::qi::registerType(qi::typeId<FutT<T>>(), this);
299  ObjectTypeBuilder<FutT<T> > b(false);
301 #define ADVERTISE(meth) \
302  b.advertiseMethod(#meth, &FutT<T>::meth)
303  ADVERTISE(_connect);
304  ADVERTISE(error);
305  ADVERTISE(hasError);
306  ADVERTISE(isCanceled);
307  ADVERTISE(cancel);
308  b.advertiseMethod("value",
309  (const typename FutT<T>::ValueType& (FutT<T>::*)(int) const) &FutT<T>::value);
310  ADVERTISE(waitUntil);
311  ADVERTISE(waitFor);
312  ADVERTISE(isRunning);
313  ADVERTISE(isFinished);
314  ADVERTISE(isValid);
315 #undef ADVERTISE
316  // this method is useful to get a future<anyvalue> through a simple async call
317  // it is used in libqi-python
318  b.advertiseMethod("_getSelf",
319  static_cast<qi::Future<T>(*)(FutT<T>*)>(
320  [](FutT<T>* fut) -> qi::Future<T> {
321  return *fut;
322  }));
323  this->initialize(b.metaObject(), b.typeData());
324  }
326  {
327  return typeOf<T>();
328  }
331 };
332 template <typename T>
333 class TypeOfTemplateImpl<qi::Future, T> : public TypeOfTemplateFutImpl<qi::Future, T> {};
334 template <typename T>
335 class TypeOfTemplateImpl<qi::FutureSync, T> : public TypeOfTemplateFutImpl<qi::FutureSync, T> {};
336 }
338 QI_TEMPLATE_TYPE_DECLARE(qi::FutureSync)
339 
340 QI_MT_TEMPLATE_OBJECT(qi::Promise, setValue, setError, setCanceled, future, value, trigger);
341 
342 namespace qi { namespace detail {
343  template<typename T> struct TypeManager<Future<T> >: public TypeManagerDefaultStruct<Future<T> > {};
344  template<typename T> struct TypeManager<FutureSync<T> >: public TypeManagerDefaultStruct<FutureSync<T> > {};
345  template<typename T> struct TypeManager<Promise<T> >: public TypeManagerDefaultStruct<Promise<T> > {};
346 }}
347 
348 #endif // _QITYPE_OBJECTTYPEBUILDER_HPP_
void setValue(qi::Promise< R > &p, const boost::function< R()> &f)
TypeIndex typeId()
#define ADVERTISE(meth)
#define QI_API
Definition: api.hpp:33
const detail::ObjectTypeData & typeData()
bool registerType(const TypeIndex &typeId, TypeInterface *type)
Runtime Type factory setter.
boost::function< SignalBase *(void *)> SignalMemberGetter
AnyObject object(T *ptr, boost::function< void(GenericObject *)> onDestroy=boost::function< void(GenericObject *)>())
Honor the default behavior.
Definition: typeobject.hpp:26
virtual void registerType()
Register type to typeof. Called by type()
class QITYPE_TEMPLATE_API TypeOfTemplate
Definition: type.hxx:136
dll import/export and compiler message
virtual void registerType()
Register type to typeOf<T>, to avoid both TypeImpl<T> and type() being present.
Object is thread safe, multiple calls can occur in different threads in parallel. ...
Definition: manageable.hpp:38
boost::function< PropertyBase *(void *)> PropertyMemberGetter
ObjectTypeBuilder(bool autoRegister=true)
#define QI_MT_TEMPLATE_OBJECT(name,...)
MetaCallType
Definition: typeobject.hpp:24
void setThreadingModel(ObjectThreadingModel model)
unsigned int advertiseMethod(const std::string &name, FUNCTION_TYPE function, MetaCallType threadingModel=MetaCallType_Auto, int id=-1)
TypeInterface * templateArgument() override
const MetaObject & metaObject()
unsigned int advertiseFactory(const std::string &name)
unsigned int advertise(ObjectTypeBuilderBase *builder, const std::string &name, A accessor, Dummy< 0 >)
ObjectThreadingModel
Possible thread models for an object.
Definition: manageable.hpp:33
QI_TEMPLATE_TYPE_DECLARE(qi::Promise)
Description of the signals and methods accessible on an ObjectTypeInterface.
Definition: metaobject.hpp:25