libqi-api  2.4.3.28
 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_DETAILS_OBJECTTYPEBUILDER_HXX_
8 #define _QITYPE_DETAILS_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 
51  template <typename FUNCTION_TYPE>
52  unsigned int ObjectTypeBuilderBase::advertiseMethod(const std::string& name,
53  FUNCTION_TYPE function,
54  MetaCallType threadingModel,
55  int id)
56  {
57  MetaMethodBuilder builder;
58  AnyFunction f = AnyFunction::from(function);
59  builder.setName(name);
60  builder.setSignature(f);
61 
62  // throw on error
63  return xAdvertiseMethod(builder, f, threadingModel, id);
64  }
65 
66  template <typename FUNCTION_TYPE>
68  FUNCTION_TYPE function,
69  MetaCallType threadingModel,
70  int id)
71  {
72  AnyFunction f = AnyFunction::from(function);
73  builder.setSignature(f);
74 
75  // throw on error
76  return xAdvertiseMethod(builder, f, threadingModel, id);
77  }
78 
79  template<typename U>
81  {
82  return inherits(typeOf<
83  typename boost::remove_reference<U>::type>(), offset);
84  }
85 
86  template<typename T>
87  template<typename U>
89  {
90  qiLogCategory("qitype.objectbuilder");
91  // Compute the offset between T and U
92  T* ptr = reinterpret_cast<T*>(0x10000);
93  U* pptr = ptr;
94  intptr_t offset = reinterpret_cast<intptr_t>(pptr) - reinterpret_cast<intptr_t>(ptr);
95  qiLogDebug() << "Offset check T(" << typeid(ptr).name() << ")= " << pptr << ", U(" << typeid(ptr).name() << ")= " << ptr << ", T-U= " << offset;
96  return ObjectTypeBuilderBase::inherits<U>(offset);
97  }
98 
99  namespace detail
100  {
101  template<typename F, typename T> void checkRegisterParent(
102  ObjectTypeBuilder<T>& , boost::false_type) {}
103  template<typename F, typename T> void checkRegisterParent(
104  ObjectTypeBuilder<T>& builder, boost::true_type)
105  {
106  typedef typename boost::function_types::parameter_types<F>::type ArgsType;
107  typedef typename boost::mpl::front<ArgsType>::type DecoratedClassType;
108  typedef typename boost::remove_reference<DecoratedClassType>::type ClassType;
109  builder.template inherits<ClassType>();
110  }
111  };
112 
113  template <typename T>
114  template <typename FUNCTION_TYPE>
115  unsigned int ObjectTypeBuilder<T>::advertiseMethod(const std::string& name, FUNCTION_TYPE function, MetaCallType threadingModel, int id)
116  {
117  // Intercept advertise to auto-register parent type if this is a parent method
118  // Note: if FUNCTION_TYPE is a grandparent method, we will incorrectly add it
119  // as a child
120  detail::checkRegisterParent<FUNCTION_TYPE>(
121  *this,
122  typename boost::function_types::is_member_function_pointer<FUNCTION_TYPE >::type());
123 
124  // throw on error
125  return ObjectTypeBuilderBase::advertiseMethod(name, function, threadingModel, id);
126  }
127 
128  template <typename T>
129  template <typename FUNCTION_TYPE>
130  unsigned int ObjectTypeBuilder<T>::advertiseMethod(MetaMethodBuilder& name, FUNCTION_TYPE function, MetaCallType threadingModel, int id)
131  {
132  // Intercept advertise to auto-register parent type if this is a parent method
133  // Note: if FUNCTION_TYPE is a grandparent method, we will incorrectly add it
134  // as a child
135  detail::checkRegisterParent<FUNCTION_TYPE>(
136  *this,
137  typename boost::function_types::is_member_function_pointer<FUNCTION_TYPE >::type());
138 
139  // throw on error
140  return ObjectTypeBuilderBase::advertiseMethod(name, function, threadingModel, id);
141  }
142 
143  template <typename T>
144  AnyObject ObjectTypeBuilder<T>::object(T* ptr, boost::function<void (GenericObject*)> onDestroy)
145  {
146  return ObjectTypeBuilderBase::object(static_cast<void*>(ptr), onDestroy);
147  }
148 
149 
150  template<typename T>
152  {
153  ::qi::registerType(typeid(T), type());
154  }
155 
156  template<typename A>
157  typename boost::enable_if<typename detail::Accessor<A>::is_accessor, SignalBase*>::type
158  signalAccess(A acc, void* instance)
159  {
160  typedef typename detail::Accessor<A>::class_type class_type;
161  return &detail::Accessor<A>::access((class_type*)instance, acc);
162  }
163 
164  template<typename A>
165  typename boost::enable_if<typename detail::Accessor<A>::is_accessor, PropertyBase*>::type
166  propertyAccess(A acc, void* instance)
167  {
168  typedef typename detail::Accessor<A>::class_type class_type;
169  return &detail::Accessor<A>::access((class_type*)instance, acc);
170  }
171 
172  template<typename A>
173  unsigned int
174  ObjectTypeBuilderBase::advertiseSignal(const std::string& eventName, A accessor, int id)
175  {
176  SignalMemberGetter fun = boost::bind(&signalAccess<A>, accessor, _1);
177  typedef typename detail::Accessor<A>::value_type::FunctionType FunctionType;
178  return xAdvertiseSignal(eventName,
180  }
181 
182  template <typename A>
183  unsigned int ObjectTypeBuilderBase::advertiseProperty(const std::string& name, A accessor)
184  {
185  unsigned int id = advertiseSignal(name, accessor);
186  PropertyMemberGetter pg = boost::bind(&propertyAccess<A>, accessor, _1);
187  typedef typename detail::Accessor<A>::value_type::PropertyType PropertyType;
188  return xAdvertiseProperty(name, typeOf<PropertyType>()->signature(), pg, id);
189  }
190 
191  template <typename T> unsigned int ObjectTypeBuilderBase::advertiseSignal(const std::string& name, SignalMemberGetter getter, int id)
192  {
193  return xAdvertiseSignal(name, detail::FunctionSignature<T>::signature(), getter, id);
194  }
195 
196  template<typename T>
197  inline unsigned int ObjectTypeBuilderBase::advertiseProperty(const std::string& eventName, PropertyMemberGetter getter)
198  {
199  return xAdvertiseProperty(eventName, typeOf<T>()->signature(), getter);
200  }
201 
202 
203  namespace detail
204  {
205  static const char* interfaceMarker = "_interface_";
206  static const unsigned int interfaceMarkerLength = strlen(interfaceMarker);
207 
208  // Trait that detect inheritance from PropertyBase SignalBase or none of the above.
209 
210  template<typename T, bool b> struct SigPropInheritsSignal
211  {};
212  template<typename T, bool b> struct SigPropInheritsProperty
213  {};
214 
215  template<typename T> struct SigProp : public
216  SigPropInheritsProperty<T, boost::is_base_of<PropertyBase, T>::value> {};
217 
218  template<typename T> struct SigPropInheritsProperty<T, true>
219  {
220  static const unsigned value = 2;
221  };
222  template<typename T> struct SigPropInheritsProperty<T, false>
223  : public SigPropInheritsSignal<T, boost::is_base_of<SignalBase, T>::value> {};
224 
225  template<typename T> struct SigPropInheritsSignal<T, true>
226  {
227  static const unsigned value = 1;
228  };
229  template<typename T> struct SigPropInheritsSignal<T, false>
230  {
231  static const unsigned value = 0;
232  };
233 
234  template<unsigned> struct Dummy {};
235  template<typename A> unsigned int advertise(ObjectTypeBuilderBase* builder, const std::string& name, A accessor, Dummy<0>)
236  {
237  return builder->advertiseMethod(name, accessor);
238  }
239  template<typename A> unsigned int advertise(ObjectTypeBuilderBase* builder, const std::string& name, A accessor, Dummy<1>)
240  {
241  std::string n = name;
242  if (n.size() > interfaceMarkerLength && n.substr(0, interfaceMarkerLength) == interfaceMarker)
243  n = name.substr(interfaceMarkerLength);
244  return builder->advertiseSignal(n, accessor);
245  }
246  template<typename A> unsigned int advertise(ObjectTypeBuilderBase* builder, const std::string& name, A accessor, Dummy<2>)
247  {
248  std::string n = name;
249  if (n.size() > interfaceMarkerLength && n.substr(0, interfaceMarkerLength) == interfaceMarker)
250  n = name.substr(interfaceMarkerLength);
251  return builder->advertiseProperty(n, accessor);
252  }
253  template<typename A> unsigned int advertiseBounce(ObjectTypeBuilderBase* builder, const std::string& name, A accessor, boost::true_type)
254  {
255  return advertise(builder, name, accessor,
256  Dummy<detail::SigProp<typename detail::Accessor<A>::value_type>::value>());
257  }
258  template<typename A> unsigned int advertiseBounce(ObjectTypeBuilderBase* builder, const std::string& name, A accessor, boost::false_type)
259  {
260  return builder->advertiseMethod(name, accessor);
261  }
262  }
263  template<typename T>
264  unsigned int
265  ObjectTypeBuilderBase::advertiseId(const std::string& name, T element)
266  {
267  return detail::advertiseBounce(this, name, element, typename detail::Accessor<T>::is_accessor());
268  }
269  template<typename T>
271  ObjectTypeBuilderBase::advertise(const std::string& name, T element)
272  {
273  detail::advertiseBounce(this, name, element, typename detail::Accessor<T>::is_accessor());
274  return *this;
275  }
276 
277 }
278 
279 
280 #endif // _QITYPE_DETAILS_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.
static AnyFunction from(F func)
qi::Strand * callWithVoid(qi::Strand *(T::*member)() const, void *instance)
#define qiLogCategory(Cat)
Definition: log.hpp:46
boost::function< RF > bind(const AF &fun,...)
void xBuildFor(TypeInterface *type, bool autoRegister, qi::AnyFunction strandAccessor)
#define qiLogDebug(...)
Definition: log.hpp:69
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)
void setName(const std::string &name)
AnyObject object(void *ptr, boost::function< void(GenericObject *)> onDestroy=boost::function< void(GenericObject *)>())
boost::function< SignalBase *(void *)> SignalMemberGetter
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:19
unsigned int xAdvertiseSignal(const std::string &name, const qi::Signature &signature, SignalMemberGetter getter, int id=-1)
TypeInterface * typeOf()
Definition: type.hxx:91
boost::enable_if< typename detail::Accessor< A >::is_accessor, SignalBase * >::type signalAccess(A acc, void *instance)
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)
unsigned int xAdvertiseMethod(MetaMethodBuilder &builder, AnyFunction func, MetaCallType threadingModel=MetaCallType_Auto, int id=-1)