libqi-api  2.8.7.4
 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 
54  ObjectUid uid(void* instance) const override
55  {
56  QI_ASSERT_TRUE(instance);
57  Proxy* ptr = toProxy(instance);
58  return ptr->asObject().uid();
59  }
60 
61  qi::Future<AnyReference> metaCall(void* instance, AnyObject context, unsigned int method, const GenericFunctionParameters& params, MetaCallType callType, Signature returnSignature) override
62  {
63  Proxy* ptr = toProxy(instance);
64  return ptr->asObject().metaCall(method, params, callType, returnSignature);
65  }
66  void metaPost(void* instance, AnyObject context, unsigned int signal, const GenericFunctionParameters& params) override
67  {
68  Proxy* ptr = toProxy(instance);
69  ptr->asObject().metaPost(signal, params);
70  }
71  qi::Future<SignalLink> connect(void* instance, AnyObject context, unsigned int event, const SignalSubscriber& subscriber) override
72  {
73  Proxy* ptr = toProxy(instance);
74  return ptr->asObject().connect(event, subscriber);
75  }
76  qi::Future<void> disconnect(void* instance, AnyObject context, SignalLink linkId) override
77  {
78  Proxy* ptr = toProxy(instance);
79  return ptr->asObject().disconnect(linkId);
80  }
81  const std::vector<std::pair<TypeInterface*, std::ptrdiff_t> >& parentTypes() override
82  {
83  using ReturnType = typename std::decay<decltype(parentTypes())>::type;
84  static ReturnType* parents = nullptr;
85 
86  static const auto init = []{ return new ReturnType{
87  { qi::typeOf<InterfaceType>(), []{
88  ProxyType* ptr = static_cast<ProxyType*>(reinterpret_cast<void*>(0x10000));
89  InterfaceType* pptr = ptr;
90  std::ptrdiff_t offset = reinterpret_cast<intptr_t>(pptr)-reinterpret_cast<intptr_t>(ptr);
91  return offset;
92  }()
93  }
94  };
95  };
96 
97  QI_ONCE(parents = init());
98 
99  return *parents;
100  }
101  qi::Future<AnyValue> property(void* instance, AnyObject context, unsigned int id) override
102  {
103  Proxy* ptr = toProxy(instance);
104  GenericObject* obj = ptr->asObject().asGenericObject();
105  return obj->type->property(obj->value, context, id);
106  }
107  qi::Future<void> setProperty(void* instance, AnyObject context, unsigned int id, AnyValue value) override
108  {
109  Proxy* ptr = toProxy(instance);
110  GenericObject* obj = ptr->asObject().asGenericObject();
111  return obj->type->setProperty(obj->value, context, id, value);
112  }
116 };
117 
118 namespace detail
119 {
120  // FIXME: inline that in QI_REGISTER_PROXY_INTERFACE maybe
121  template<typename ProxyImpl> Proxy* static_proxy_cast(void* storage)
122  {
123  return static_cast<Proxy*>((ProxyImpl*)storage);
124  }
125 
126  template<class InterfaceType, typename ProxyImpl>
128  {
129  static TypeProxy<InterfaceType, ProxyImpl>* result = 0;
130  if (!result)
131  result = new TypeProxy<InterfaceType, ProxyImpl>(&static_proxy_cast<ProxyImpl>);
132  return result;
133  }
134 
135  template<typename ProxyImpl>
137  {
138  boost::shared_ptr<ProxyImpl> sp(new ProxyImpl(ptr));
139  return AnyReference::from(sp).clone();
140  }
141 }
142 
149 template<typename Proxy, typename Interface>
151 {
152  qiLogVerbose("qitype.type") << "ProxyInterface registration " << typeOf<Interface>()->infoString();
153  // Runtime-register TypeInterface for Proxy, using ProxyInterface with
154  // proper static_cast (from Proxy template to qi::Proxy) helper.
155  registerType(qi::typeId<Proxy>(), detail::makeProxyInterface<Interface, Proxy>());
157  map[typeOf<Interface>()->info()] = boost::function<AnyReference(AnyObject)>(&detail::makeProxy<Proxy>);
158  return true;
159 }
160 
161 }
162 
163 #define QI_REGISTER_PROXY(Proxy) \
164  namespace { \
165  static bool BOOST_PP_CAT(_qi_register_proxy_, Proxy) QI_ATTR_UNUSED = \
166  ::qi::registerProxy<Proxy>(); \
167  }
168 
169 #define QI_REGISTER_PROXY_INTERFACE(Proxy, Interface) \
170  namespace { \
171  static bool BOOST_PP_CAT(_qi_register_proxy_, Proxy) QI_ATTR_UNUSED = \
172  ::qi::registerProxyInterface<Proxy, Interface>(); \
173  }
174 
175 #endif
GenericObject * asGenericObject() const
Definition: object.hxx:652
_QI_BOUNCE_TYPE_METHODS(Methods)
#define QI_API
Definition: api.hpp:33
qi::FutureSync< void > disconnect(SignalLink linkId) const
Definition: object.hxx:106
qi::Future< AnyValue > property(void *instance, AnyObject context, unsigned int id) override
bool registerProxyInterface()
bool registerType(const TypeIndex &typeId, TypeInterface *type)
Runtime Type factory setter.
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:76
#define qiLogVerbose(...)
Log in verbose mode. This level is not shown by default.
Definition: log.hpp:87
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:91
virtual qi::Future< void > setProperty(void *instance, AnyObject context, unsigned int id, AnyValue value)=0
T & asT() const
Definition: object.hxx:635
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
const std::vector< std::pair< TypeInterface *, std::ptrdiff_t > > & parentTypes() override
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:38
const MetaObject & metaObject() const
Definition: object.hxx:64
void metaPost(unsigned int event, const GenericFunctionParameters &params) const
Definition: object.hxx:77
ObjectTypeInterface * type
#define QI_ONCE(code)
Execute code once, parallel calls are blocked until code finishes.
Definition: atomic.hpp:420
MetaCallType
Definition: typeobject.hpp:24
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)
ObjectUid uid(void *instance) const override
Object< Empty > AnyObject
Definition: anyobject.hpp:21
#define QI_ASSERT_TRUE(expr__)
Definition: assert.hpp:31
AnyReference clone() const
qi::Future< AnyReference > metaCall(unsigned int method, const GenericFunctionParameters &params, MetaCallType callType=MetaCallType_Auto, Signature returnSignature=Signature()) const
Definition: object.hxx:65
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:36
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 Creates and registers the default log handler according to QI_DE...
int context()
Get log context.
Description of the signals and methods accessible on an ObjectTypeInterface.
Definition: metaobject.hpp:25