libqi-api  release-2.5.3-2016-11-18
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Pages
proxyregister.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 _QITYPE_DETAIL_PROXY_REGISTER_HPP_
8 #define _QITYPE_DETAIL_PROXY_REGISTER_HPP_
9 
10 namespace qi
11 {
12 
16 class QI_API Proxy : public boost::noncopyable
17 {
18 public:
19  Proxy(AnyObject obj) : _obj(obj) {qiLogDebug("qitype.proxy") << "Initializing " << this;}
20  Proxy() {}
21  ~Proxy() { qiLogDebug("qitype.proxy") << "Finalizing on " << this;}
22  Object<Empty> asObject() const;
23 protected:
25 };
26 
27 inline AnyObject Proxy::asObject() const
28 {
29  qiLogDebug("qitype.proxy") << "asObject " << this << ' ' << &_obj.asT();
30  return AnyObject(_obj);
31 }
32 
33 /* A proxy instance can have members: signals and properties, inherited from interface.
34 * So it need a type of its own, we cannot pretend it's a AnyObject.
35 */
36 template<class InterfaceType, class ProxyType>
38 {
39 public:
40  /* We need a per-instance offset from effective type to Proxy.
41  * Avoid code explosion by putting it per-instance
42  */
43  using ToProxy = boost::function<Proxy*(void*)>;
45  : toProxy(toProxy)
46  {
47  }
48  const MetaObject& metaObject(void* instance) override
49  {
50  Proxy* ptr = toProxy(instance);
51  return ptr->asObject().metaObject();
52  }
53  qi::Future<AnyReference> metaCall(void* instance, AnyObject context, unsigned int method, const GenericFunctionParameters& params, MetaCallType callType, Signature returnSignature) override
54  {
55  Proxy* ptr = toProxy(instance);
56  return ptr->asObject().metaCall(method, params, callType, returnSignature);
57  }
58  void metaPost(void* instance, AnyObject context, unsigned int signal, const GenericFunctionParameters& params) override
59  {
60  Proxy* ptr = toProxy(instance);
61  ptr->asObject().metaPost(signal, params);
62  }
63  qi::Future<SignalLink> connect(void* instance, AnyObject context, unsigned int event, const SignalSubscriber& subscriber) override
64  {
65  Proxy* ptr = toProxy(instance);
66  return ptr->asObject().connect(event, subscriber);
67  }
68  qi::Future<void> disconnect(void* instance, AnyObject context, SignalLink linkId) override
69  {
70  Proxy* ptr = toProxy(instance);
71  return ptr->asObject().disconnect(linkId);
72  }
73  const std::vector<std::pair<TypeInterface*, int> >& parentTypes() override
74  {
75  using ReturnType = typename std::decay<decltype(parentTypes())>::type;
76  static ReturnType* parents = nullptr;
77 
78  static const auto init = []{ return new ReturnType{
79  { qi::typeOf<InterfaceType>(), []{
80  ProxyType* ptr = static_cast<ProxyType*>(reinterpret_cast<void*>(0x10000));
81  InterfaceType* pptr = ptr;
82  intptr_t offset = reinterpret_cast<intptr_t>(pptr)-reinterpret_cast<intptr_t>(ptr);
83  return offset;
84  }()
85  }
86  };
87  };
88 
89  QI_ONCE(parents = init());
90 
91  return *parents;
92  }
93  qi::Future<AnyValue> property(void* instance, AnyObject context, unsigned int id) override
94  {
95  Proxy* ptr = toProxy(instance);
96  GenericObject* obj = ptr->asObject().asGenericObject();
97  return obj->type->property(obj->value, context, id);
98  }
99  qi::Future<void> setProperty(void* instance, AnyObject context, unsigned int id, AnyValue value) override
100  {
101  Proxy* ptr = toProxy(instance);
102  GenericObject* obj = ptr->asObject().asGenericObject();
103  return obj->type->setProperty(obj->value, context, id, value);
104  }
108 };
109 
110 namespace detail
111 {
112  // FIXME: inline that in QI_REGISTER_PROXY_INTERFACE maybe
113  template<typename ProxyImpl> Proxy* static_proxy_cast(void* storage)
114  {
115  return static_cast<Proxy*>((ProxyImpl*)storage);
116  }
117 
118  template<class InterfaceType, typename ProxyImpl>
120  {
121  static TypeProxy<InterfaceType, ProxyImpl>* result = 0;
122  if (!result)
123  result = new TypeProxy<InterfaceType, ProxyImpl>(&static_proxy_cast<ProxyImpl>);
124  return result;
125  }
126 
127  template<typename ProxyImpl>
129  {
130  boost::shared_ptr<ProxyImpl> sp(new ProxyImpl(ptr));
131  return AnyReference::from(sp).clone();
132  }
133 }
134 
141 template<typename Proxy, typename Interface>
143 {
144  qiLogVerbose("qitype.type") << "ProxyInterface registration " << typeOf<Interface>()->infoString();
145  // Runtime-register TypeInterface for Proxy, using ProxyInterface with
146  // proper static_cast (from Proxy template to qi::Proxy) helper.
147  registerType(typeid(Proxy), detail::makeProxyInterface<Interface, Proxy>());
149  map[typeOf<Interface>()->info()] = boost::function<AnyReference(AnyObject)>(&detail::makeProxy<Proxy>);
150  return true;
151 }
152 
153 }
154 
155 #define QI_REGISTER_PROXY(Proxy) \
156  namespace { \
157  static bool BOOST_PP_CAT(_qi_register_proxy_, Proxy) = \
158  ::qi::registerProxy<Proxy>(); \
159  }
160 
161 #define QI_REGISTER_PROXY_INTERFACE(Proxy, Interface) \
162  namespace { \
163  static bool BOOST_PP_CAT(_qi_register_proxy_, Proxy) = \
164  ::qi::registerProxyInterface<Proxy, Interface>(); \
165  }
166 
167 #endif
GenericObject * asGenericObject() const
Definition: object.hxx:530
_QI_BOUNCE_TYPE_METHODS(Methods)
#define QI_API
Definition: api.hpp:33
qi::FutureSync< void > disconnect(SignalLink linkId) const
Definition: object.hxx:99
qi::Future< AnyValue > property(void *instance, AnyObject context, unsigned int id) override
bool registerProxyInterface()
qi::Future< void > disconnect(void *instance, AnyObject context, SignalLink linkId) override
Disconnect an event link. Returns if disconnection was successful.
const MetaObject & metaObject(void *instance) override
boost::function< Proxy *(void *)> ToProxy
#define qiLogDebug(...)
Definition: log.hpp:68
#define qiLogVerbose(...)
Log in verbose mode. This level is not shown by default.
Definition: log.hpp:79
qi::Future< void > setProperty(void *instance, AnyObject context, unsigned int id, AnyValue value) override
qi::FutureSync< SignalLink > connect(const std::string &eventName, FUNCTOR_TYPE callback, MetaCallType threadingModel=MetaCallType_Auto) const
Definition: object.hxx:84
virtual qi::Future< void > setProperty(void *instance, AnyObject context, unsigned int id, AnyValue value)=0
T & asT() const
Definition: object.hxx:513
virtual qi::Future< AnyValue > property(void *instance, AnyObject context, unsigned int id)=0
void metaPost(void *instance, AnyObject context, unsigned int signal, const GenericFunctionParameters &params) override
bool registerType(const std::type_info &typeId, TypeInterface *type)
Runtime Type factory setter.
qi::Future< SignalLink > connect(void *instance, AnyObject context, unsigned int event, const SignalSubscriber &subscriber) override
TypeProxy< InterfaceType, ProxyImpl > * makeProxyInterface()
ProxyGeneratorMap & proxyGeneratorMap()
Object< Empty > asObject() const
std::map< TypeInfo, boost::function< AnyReference(AnyObject)>> ProxyGeneratorMap
Definition: object.hxx:31
const MetaObject & metaObject() const
Definition: object.hxx:57
void metaPost(unsigned int event, const GenericFunctionParameters &params) const
Definition: object.hxx:70
const std::vector< std::pair< TypeInterface *, int > > & parentTypes() override
ObjectTypeInterface * type
#define QI_ONCE(code)
Execute code once, parallel calls are blocked until code finishes.
Definition: atomic.hpp:317
MetaCallType
Definition: typeobject.hpp:21
Object< Empty > _obj
const char * infoString()
virtual const TypeInfo & info()=0
Get the TypeInfo corresponding to this type.
Proxy(AnyObject obj)
AnyReference makeProxy(AnyObject ptr)
Object< Empty > AnyObject
Definition: anyobject.hpp:21
AnyReference clone() const
qi::Future< AnyReference > metaCall(unsigned int method, const GenericFunctionParameters &params, MetaCallType callType=MetaCallType_Auto, Signature returnSignature=Signature()) const
Definition: object.hxx:58
qi::Future< AnyReference > metaCall(void *instance, AnyObject context, unsigned int method, const GenericFunctionParameters &params, MetaCallType callType, Signature returnSignature) override
static AnyReference from(const T &ref)
qi::uint64_t SignalLink
Definition: signal.hpp:35
Proxy * static_proxy_cast(void *storage)
TypeProxy(ToProxy toProxy)
void init(qi::LogLevel verb=qi::LogLevel_Info, qi::LogContext context=qi::LogContextAttr_ShortVerbosity|qi::LogContextAttr_Tid|qi::LogContextAttr_Category, bool synchronous=true)
Initialization of the logging system (could be avoided)
int context()
Get log context.
Description of the signals and methods accessible on an ObjectTypeInterface.
Definition: metaobject.hpp:25