libqi-api  release-2.5.3-2016-11-18
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Pages
objecttypebuilder.hxx
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 _QITYPE_DETAIL_OBJECTTYPEBUILDER_HXX_
8 #define _QITYPE_DETAIL_OBJECTTYPEBUILDER_HXX_
9 
10 #include <boost/function_types/is_member_function_pointer.hpp>
11 #include <boost/mpl/front.hpp>
13 #include <qi/type/metamethod.hpp>
14 #include <qi/actor.hpp>
15 
16 namespace qi {
17 
18  namespace detail {
19  template <typename T>
20  qi::Strand* callWithVoid(qi::Strand* (T::*member)() const, void* instance)
21  {
22  return (static_cast<T*>(instance)->*member)();
23  }
24 
25  template <typename T>
26  typename boost::enable_if<boost::is_base_of<Actor, T>, AnyFunction>::type
28  {
29  return AnyFunction::from(boost::function<qi::Strand*(void*)>(
30  boost::bind(&callWithVoid<T>, &T::strand, _1)));
31  }
32  template <typename T>
33  typename boost::disable_if<boost::is_base_of<Actor, T>, AnyFunction>::type
35  {
36  return AnyFunction();
37  }
38  }
39 
40  template<typename T> void ObjectTypeBuilderBase::buildFor(bool autoRegister)
41  {
42  // We are erasing T here: we must pass everything the builder need to know about t:
43  // - typeid
44  // - cloner/deleter
45  // - serializer, ...
46  // => wee need all TypeInterface* methods, but we do not want another TypeInterface*
47  // to anwser to typeOf<T>
48  xBuildFor(new DefaultTypeImpl<T>(), autoRegister, detail::getStrandAccessor<T>());
49 
50  if (std::is_base_of<Actor, T>::value)
52  else
54  }
55 
56  template <typename FUNCTION_TYPE>
57  unsigned int ObjectTypeBuilderBase::advertiseMethod(const std::string& name,
58  FUNCTION_TYPE function,
59  MetaCallType threadingModel,
60  int id)
61  {
62  MetaMethodBuilder builder;
63  AnyFunction f = AnyFunction::from(function);
64  builder.setName(name);
65  builder.setSignature(f);
66 
67  // throw on error
68  return xAdvertiseMethod(builder, f, threadingModel, id);
69  }
70 
71  template <typename FUNCTION_TYPE>
73  FUNCTION_TYPE function,
74  MetaCallType threadingModel,
75  int id)
76  {
77  AnyFunction f = AnyFunction::from(function);
78  builder.setSignature(f);
79 
80  // throw on error
81  return xAdvertiseMethod(builder, f, threadingModel, id);
82  }
83 
84  template<typename U>
86  {
87  return inherits(typeOf<
88  typename boost::remove_reference<U>::type>(), offset);
89  }
90 
91  template<typename T>
92  template<typename U>
94  {
95  qiLogCategory("qitype.objectbuilder");
96  // Compute the offset between T and U
97  T* ptr = reinterpret_cast<T*>(0x10000);
98  U* pptr = ptr;
99  intptr_t offset = reinterpret_cast<intptr_t>(pptr) - reinterpret_cast<intptr_t>(ptr);
100  qiLogDebug() << "Offset check T(" << typeid(ptr).name() << ")= " << pptr << ", U(" << typeid(ptr).name() << ")= " << ptr << ", T-U= " << offset;
101  return ObjectTypeBuilderBase::inherits<U>(offset);
102  }
103 
104  namespace detail
105  {
106  template<typename F, typename T> void checkRegisterParent(
107  ObjectTypeBuilder<T>& , boost::false_type) {}
108  template<typename F, typename T> void checkRegisterParent(
109  ObjectTypeBuilder<T>& builder, boost::true_type)
110  {
111  using ArgsType = typename boost::function_types::parameter_types<F>::type;
112  using DecoratedClassType = typename boost::mpl::front<ArgsType>::type;
113  using ClassType = typename boost::remove_reference<DecoratedClassType>::type;
114  builder.template inherits<ClassType>();
115  }
116  };
117 
118  template <typename T>
119  template <typename FUNCTION_TYPE>
120  unsigned int ObjectTypeBuilder<T>::advertiseMethod(const std::string& name, FUNCTION_TYPE function, MetaCallType threadingModel, int id)
121  {
122  // Intercept advertise to auto-register parent type if this is a parent method
123  // Note: if FUNCTION_TYPE is a grandparent method, we will incorrectly add it
124  // as a child
125  detail::checkRegisterParent<FUNCTION_TYPE>(
126  *this,
127  typename boost::function_types::is_member_function_pointer<FUNCTION_TYPE >::type());
128 
129  // throw on error
130  return ObjectTypeBuilderBase::advertiseMethod(name, function, threadingModel, id);
131  }
132 
133  template <typename T>
134  template <typename FUNCTION_TYPE>
135  unsigned int ObjectTypeBuilder<T>::advertiseMethod(MetaMethodBuilder& name, FUNCTION_TYPE function, MetaCallType threadingModel, int id)
136  {
137  // Intercept advertise to auto-register parent type if this is a parent method
138  // Note: if FUNCTION_TYPE is a grandparent method, we will incorrectly add it
139  // as a child
140  detail::checkRegisterParent<FUNCTION_TYPE>(
141  *this,
142  typename boost::function_types::is_member_function_pointer<FUNCTION_TYPE >::type());
143 
144  // throw on error
145  return ObjectTypeBuilderBase::advertiseMethod(name, function, threadingModel, id);
146  }
147 
148  template <typename T>
149  AnyObject ObjectTypeBuilder<T>::object(T* ptr, boost::function<void (GenericObject*)> onDestroy)
150  {
151  return ObjectTypeBuilderBase::object(static_cast<void*>(ptr), onDestroy);
152  }
153 
154 
155  template<typename T>
157  {
158  ::qi::registerType(typeid(T), type());
159  }
160 
161  template<typename A>
162  typename boost::enable_if<typename detail::Accessor<A>::is_accessor, SignalBase*>::type
163  signalAccess(A acc, void* instance)
164  {
165  using class_type = typename detail::Accessor<A>::class_type;
166  return &detail::Accessor<A>::access((class_type*)instance, acc);
167  }
168 
169  template<typename A>
170  typename boost::enable_if<typename detail::Accessor<A>::is_accessor, PropertyBase*>::type
171  propertyAccess(A acc, void* instance)
172  {
173  using class_type = typename detail::Accessor<A>::class_type;
174  return &detail::Accessor<A>::access((class_type*)instance, acc);
175  }
176 
177  template<typename A>
178  unsigned int
179  ObjectTypeBuilderBase::advertiseSignal(const std::string& eventName, A accessor, int id)
180  {
181  SignalMemberGetter fun = boost::bind(&signalAccess<A>, accessor, _1);
182  using FunctionType = typename detail::Accessor<A>::value_type::FunctionType;
183  return xAdvertiseSignal(eventName,
185  }
186 
187  template <typename A>
188  unsigned int ObjectTypeBuilderBase::advertiseProperty(const std::string& name, A accessor)
189  {
190  unsigned int id = advertiseSignal(name, accessor);
191  PropertyMemberGetter pg = boost::bind(&propertyAccess<A>, accessor, _1);
192  using PropertyType = typename detail::Accessor<A>::value_type::PropertyType;
193  return xAdvertiseProperty(name, typeOf<PropertyType>()->signature(), pg, id);
194  }
195 
196  template <typename T> unsigned int ObjectTypeBuilderBase::advertiseSignal(const std::string& name, SignalMemberGetter getter, int id)
197  {
198  return xAdvertiseSignal(name, detail::FunctionSignature<T>::signature(), getter, id);
199  }
200 
201  template<typename T>
202  inline unsigned int ObjectTypeBuilderBase::advertiseProperty(const std::string& eventName, PropertyMemberGetter getter)
203  {
204  return xAdvertiseProperty(eventName, typeOf<T>()->signature(), getter);
205  }
206 
207 
208  namespace detail
209  {
210  static const char* interfaceMarker = "_interface_";
211  static const unsigned int interfaceMarkerLength = strlen(interfaceMarker);
212 
213  // Trait that detect inheritance from PropertyBase SignalBase or none of the above.
214 
215  template<typename T, bool b> struct SigPropInheritsSignal
216  {};
217  template<typename T, bool b> struct SigPropInheritsProperty
218  {};
219 
220  template<typename T> struct SigProp : public
221  SigPropInheritsProperty<T, boost::is_base_of<PropertyBase, T>::value> {};
222 
223  template<typename T> struct SigPropInheritsProperty<T, true>
224  {
225  static const unsigned value = 2;
226  };
227  template<typename T> struct SigPropInheritsProperty<T, false>
228  : public SigPropInheritsSignal<T, boost::is_base_of<SignalBase, T>::value> {};
229 
230  template<typename T> struct SigPropInheritsSignal<T, true>
231  {
232  static const unsigned value = 1;
233  };
234  template<typename T> struct SigPropInheritsSignal<T, false>
235  {
236  static const unsigned value = 0;
237  };
238 
239  template<unsigned> struct Dummy {};
240  template<typename A> unsigned int advertise(ObjectTypeBuilderBase* builder, const std::string& name, A accessor, Dummy<0>)
241  {
242  return builder->advertiseMethod(name, accessor);
243  }
244  template<typename A> unsigned int advertise(ObjectTypeBuilderBase* builder, const std::string& name, A accessor, Dummy<1>)
245  {
246  std::string n = name;
247  if (n.size() > interfaceMarkerLength && n.substr(0, interfaceMarkerLength) == interfaceMarker)
248  n = name.substr(interfaceMarkerLength);
249  return builder->advertiseSignal(n, accessor);
250  }
251  template<typename A> unsigned int advertise(ObjectTypeBuilderBase* builder, const std::string& name, A accessor, Dummy<2>)
252  {
253  std::string n = name;
254  if (n.size() > interfaceMarkerLength && n.substr(0, interfaceMarkerLength) == interfaceMarker)
255  n = name.substr(interfaceMarkerLength);
256  return builder->advertiseProperty(n, accessor);
257  }
258  template<typename A> unsigned int advertiseBounce(ObjectTypeBuilderBase* builder, const std::string& name, A accessor, boost::true_type)
259  {
260  return advertise(builder, name, accessor,
261  Dummy<detail::SigProp<typename detail::Accessor<A>::value_type>::value>());
262  }
263  template<typename A> unsigned int advertiseBounce(ObjectTypeBuilderBase* builder, const std::string& name, A accessor, boost::false_type)
264  {
265  return builder->advertiseMethod(name, accessor);
266  }
267  }
268  template<typename T>
269  unsigned int
270  ObjectTypeBuilderBase::advertiseId(const std::string& name, T element)
271  {
272  return detail::advertiseBounce(this, name, element, typename detail::Accessor<T>::is_accessor());
273  }
274  template<typename T>
276  ObjectTypeBuilderBase::advertise(const std::string& name, T element)
277  {
278  detail::advertiseBounce(this, name, element, typename detail::Accessor<T>::is_accessor());
279  return *this;
280  }
281 
282 }
283 
284 
285 #endif // _QITYPE_DETAIL_OBJECTTYPEBUILDER_HXX_
unsigned int xAdvertiseProperty(const std::string &name, const qi::Signature &signature, PropertyMemberGetter getter, int id=-1)
void buildFor(bool autoRegister=true)
Declare the class type for which this StaticBuilder is.
qi::Strand * callWithVoid(qi::Strand *(T::*member)() const, void *instance)
#define qiLogCategory(Cat)
Definition: log.hpp:45
void xBuildFor(TypeInterface *type, bool autoRegister, qi::AnyFunction strandAccessor)
#define qiLogDebug(...)
Definition: log.hpp:68
boost::function< SignalBase *(void *)> SignalMemberGetter
AnyObject object(T *ptr, boost::function< void(GenericObject *)> onDestroy=boost::function< void(GenericObject *)>())
unsigned int advertiseMethod(const std::string &name, FUNCTION_TYPE function, MetaCallType threadingModel=MetaCallType_Auto, int id=-1)
unsigned int advertiseSignal(const std::string &eventName, A accessor, int id=-1)
virtual void registerType()
Register type to typeOf<T>, to avoid both TypeImpl<T> and type() being present.
ObjectTypeBuilderBase & advertise(const std::string &name, T element)
unsigned int advertiseId(const std::string &name, T element)
Object is thread safe, multiple calls can occur in different threads in parallel. ...
Definition: manageable.hpp:38
void setName(const std::string &name)
AnyObject object(void *ptr, boost::function< void(GenericObject *)> onDestroy=boost::function< void(GenericObject *)>())
bool registerType(const std::type_info &typeId, TypeInterface *type)
Runtime Type factory setter.
void checkRegisterParent(ObjectTypeBuilder< T > &, boost::false_type)
boost::function< PropertyBase *(void *)> PropertyMemberGetter
MetaCallType
Definition: typeobject.hpp:21
void setThreadingModel(ObjectThreadingModel model)
unsigned int xAdvertiseSignal(const std::string &name, const qi::Signature &signature, SignalMemberGetter getter, int id=-1)
TypeInterface * typeOf()
Definition: type.hxx:94
boost::enable_if< typename detail::Accessor< A >::is_accessor, SignalBase * >::type signalAccess(A acc, void *instance)
static AnyFunction from(F &&func)
Object is not thread safe, all method calls must occur in the same thread.
Definition: manageable.hpp:36
unsigned int advertiseMethod(const std::string &name, FUNCTION_TYPE function, MetaCallType threadingModel=MetaCallType_Auto, int id=-1)
unsigned int advertiseProperty(const std::string &propertyName, A accessor)
unsigned int advertiseBounce(ObjectTypeBuilderBase *builder, const std::string &name, A accessor, boost::true_type)
unsigned int advertise(ObjectTypeBuilderBase *builder, const std::string &name, A accessor, Dummy< 0 >)
boost::enable_if< boost::is_base_of< Actor, T >, AnyFunction >::type getStrandAccessor()
void setSignature(const AnyFunction &f)
boost::enable_if< typename detail::Accessor< A >::is_accessor, PropertyBase * >::type propertyAccess(A acc, void *instance)
std::enable_if< std::is_function< RF >::value, boost::function< RF > >::type bind(AF &&fun, Arg0 &&arg0, Args &&...args)
Definition: trackable.hxx:327
unsigned int xAdvertiseMethod(MetaMethodBuilder &builder, AnyFunction func, MetaCallType threadingModel=MetaCallType_Auto, int id=-1)