//! \~\ingroup Core
//! \~\file piobject_macros.h
//! \~\brief
//! \~english PIObject macros for event system and object introspection
//! \~russian Макросы PIObject для событийной системы и интроспекции объектов
//! \~\details
//! \~english
//! This file declares the macro layer used by %PIObject-based classes:
//! class registration, event declaration, event handler declaration,
//! connection helpers and event raising helpers.
//! \~russian
//! Этот файл объявляет макросный слой для классов на базе %PIObject:
//! регистрацию класса, объявление событий, объявление обработчиков,
//! макросы соединения и макросы вызова событий.
/*
    PIP - Platform Independent Primitives
    Macros for PIObject
    Ivan Pelipenko peri4ko@yandex.ru

    This program is free software: you can redistribute it and/or modify
    it under the terms of the GNU Lesser General Public License as published by
    the Free Software Foundation, either version 3 of the License, or
    (at your option) any later version.

    This program is distributed in the hope that it will be useful,
    but WITHOUT ANY WARRANTY; without even the implied warranty of
    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
    GNU Lesser General Public License for more details.

    You should have received a copy of the GNU Lesser General Public License
    along with this program.  If not, see <http://www.gnu.org/licenses/>.
*/

#ifndef PIOBJECT_MACROS_H
#define PIOBJECT_MACROS_H


#ifdef DOXYGEN


//! \relatesalso PIObject
//! \~\brief
//! \~english Put this macro inside a direct %PIObject subclass definition to enable registered events, event handlers and class metadata.
//! \~russian Поместите этот макрос внутрь объявления прямого наследника %PIObject, чтобы включить регистрацию событий, обработчиков и
//! метаданных класса.
#  define PIOBJECT(name)

//! \relatesalso PIObject
//! \~\brief
//! \~english Put this macro inside a %PIObject subclass definition to inherit registered methods and class scope from "parent".
//! \~russian Поместите этот макрос внутрь объявления наследника %PIObject, чтобы унаследовать зарегистрированные методы и цепочку
//! классов от "parent".
#  define PIOBJECT_SUBCLASS(name, parent)


//! \relatesalso PIObject
//! \~\brief
//! \~english Declare a registered event handler method with signature `ret name()`.
//! \~russian Объявляет зарегистрированный метод-обработчик событий с сигнатурой `ret name()`.
#  define EVENT_HANDLER0(ret, name)                                        ret name()

//! \relatesalso PIObject
//! \~\brief
//! \~english Declare a registered event handler method with one argument.
//! \~russian Объявляет зарегистрированный метод-обработчик событий с одним аргументом.
#  define EVENT_HANDLER1(ret, name, type0, var0)                           ret name(type0 var0)

//! \relatesalso PIObject
//! \~\brief
//! \~english Declare a registered event handler method with two arguments.
//! \~russian Объявляет зарегистрированный метод-обработчик событий с двумя аргументами.
#  define EVENT_HANDLER2(ret, name, type0, var0, type1, var1)              ret name(type0 var0, type1 var1)

//! \relatesalso PIObject
//! \~\brief
//! \~english Declare a registered event handler method with three arguments.
//! \~russian Объявляет зарегистрированный метод-обработчик событий с тремя аргументами.
#  define EVENT_HANDLER3(ret, name, type0, var0, type1, var1, type2, var2) ret name(type0 var0, type1 var1, type2 var2)

//! \relatesalso PIObject
//! \~\brief
//! \~english Declare a registered event handler method with four arguments.
//! \~russian Объявляет зарегистрированный метод-обработчик событий с четырьмя аргументами.
#  define EVENT_HANDLER4(ret, name, type0, var0, type1, var1, type2, var2, type3, var3) \
	  ret name(type0 var0, type1 var1, type2 var2, type3 var3)

//! \relatesalso PIObject
//! \~\brief
//! \~english Synonym of EVENT_HANDLER0
//! \~russian Аналог EVENT_HANDLER0
#  define EVENT_HANDLER                                                     EVENT_HANDLER0


//! \relatesalso PIObject
//! \~\brief
//! \~english Declare a virtual registered event handler method with signature `virtual ret name()`.
//! \~russian Объявляет виртуальный зарегистрированный метод-обработчик с сигнатурой `virtual ret name()`.
#  define EVENT_VHANDLER0(ret, name)                                        virtual ret name()

//! \relatesalso PIObject
//! \~\brief
//! \~english Declare a virtual registered event handler method with one argument.
//! \~russian Объявляет виртуальный зарегистрированный метод-обработчик с одним аргументом.
#  define EVENT_VHANDLER1(ret, name, type0, var0)                           virtual ret name(type0 var0)

//! \relatesalso PIObject
//! \~\brief
//! \~english Declare a virtual registered event handler method with two arguments.
//! \~russian Объявляет виртуальный зарегистрированный метод-обработчик с двумя аргументами.
#  define EVENT_VHANDLER2(ret, name, type0, var0, type1, var1)              virtual ret name(type0 var0, type1 var1)

//! \relatesalso PIObject
//! \~\brief
//! \~english Declare a virtual registered event handler method with three arguments.
//! \~russian Объявляет виртуальный зарегистрированный метод-обработчик с тремя аргументами.
#  define EVENT_VHANDLER3(ret, name, type0, var0, type1, var1, type2, var2) virtual ret name(type0 var0, type1 var1, type2 var2)

//! \relatesalso PIObject
//! \~\brief
//! \~english Declare a virtual registered event handler method with four arguments.
//! \~russian Объявляет виртуальный зарегистрированный метод-обработчик с четырьмя аргументами.
#  define EVENT_VHANDLER4(ret, name, type0, var0, type1, var1, type2, var2, type3, var3) \
	  virtual ret name(type0 var0, type1 var1, type2 var2, type3 var3)

//! \relatesalso PIObject
//! \~\brief
//! \~english Synonym of EVENT_VHANDLER0
//! \~russian Аналог EVENT_VHANDLER0
#  define EVENT_VHANDLER                                                   EVENT_VHANDLER0


//! \relatesalso PIObject
//! \~\brief
//! \~english Declare an event method with no arguments.
//! \~russian Объявляет метод-событие без аргументов.
#  define EVENT0(name)                                                     void name();

//! \relatesalso PIObject
//! \~\brief
//! \~english Declare an event method with one argument.
//! \~russian Объявляет метод-событие с одним аргументом.
#  define EVENT1(name, type0, var0)                                        void name(type0 var0);

//! \relatesalso PIObject
//! \~\brief
//! \~english Declare an event method with two arguments.
//! \~russian Объявляет метод-событие с двумя аргументами.
#  define EVENT2(name, type0, var0, type1, var1)                           void name(type0 var0, type1 var1);

//! \relatesalso PIObject
//! \~\brief
//! \~english Declare an event method with three arguments.
//! \~russian Объявляет метод-событие с тремя аргументами.
#  define EVENT3(name, type0, var0, type1, var1, type2, var2)              void name(type0 var0, type1 var1, type2 var2);

//! \relatesalso PIObject
//! \~\brief
//! \~english Declare an event method with four arguments.
//! \~russian Объявляет метод-событие с четырьмя аргументами.
#  define EVENT4(name, type0, var0, type1, var1, type2, var2, type3, var3) void name(type0 var0, type1 var1, type2 var2, type3 var3);

//! \relatesalso PIObject
//! \~\brief
//! \~english Synonym of EVENT0
//! \~russian Аналог EVENT0
#  define EVENT                                                            EVENT0


//! \relatesalso PIObject
//! \~\brief
//! \~english Compatibility helper that raises event "event" on source object "src".
//! \~russian Совместимый вспомогательный макрос, вызывающий событие "event" у объекта-источника "src".
#  define RAISE_EVENT0(src, event)
//! \relatesalso PIObject
//! \~english Compatibility helper that raises event "event" with one argument.
//! \~russian Совместимый вспомогательный макрос, вызывающий событие "event" с одним аргументом.
#  define RAISE_EVENT1(src, event, v0)
//! \relatesalso PIObject
//! \~english Compatibility helper that raises event "event" with two arguments.
//! \~russian Совместимый вспомогательный макрос, вызывающий событие "event" с двумя аргументами.
#  define RAISE_EVENT2(src, event, v0, v1)
//! \relatesalso PIObject
//! \~english Compatibility helper that raises event "event" with three arguments.
//! \~russian Совместимый вспомогательный макрос, вызывающий событие "event" с тремя аргументами.
#  define RAISE_EVENT3(src, event, v0, v1, v2)
//! \relatesalso PIObject
//! \~english Compatibility helper that raises event "event" with four arguments.
//! \~russian Совместимый вспомогательный макрос, вызывающий событие "event" с четырьмя аргументами.
#  define RAISE_EVENT4(src, event, v0, v1, v2, v3)
#  define RAISE_EVENT RAISE_EVENT0


//! \relatesalso PIObject
//! \~\brief
//! \~english Connect event \"event\" from object \"src\" to event handler or event \"handler\" of object \"dest\".
//! \~russian Соединяет событие \"event\" объекта \"src\" к обработчику или событию \"handler\" объекта \"dest\".
//! \~\details
//! \~english
//! \"handler\" can accept a prefix of \"event\" arguments.
//! This macro resolves registered methods by name at run time and returns \a PIObject::Connection.
//! \~russian
//! \"handler\" может принимать только начальную часть аргументов \"event\".
//! Макрос ищет зарегистрированные методы по имени во время выполнения и возвращает \a PIObject::Connection.
#  define CONNECTU(src, event, dest, handler)

//! \relatesalso PIObject
//! \~\brief
//! \~english Connect event \"event\" from object \"src\" to event handler or event \"handler\" of object \"dest\".
//! \~russian Соединяет событие \"event\" объекта \"src\" к обработчику или событию \"handler\" объекта \"dest\".
//! \~\details
//! \~english
//! \"handler\" can accept a prefix of \"event\" arguments.
//! Delivery is queued on the performer object and runs only when that object calls
//! \a PIObject::callQueuedEvents() or \a PIObject::maybeCallQueuedEvents().
//! All argument types should be registered by \a REGISTER_VARIANT() macro, but many
//! common and PIP types already done.
//! Returns \a PIObject::Connection.
//! \~russian
//! \"handler\" может принимать только начальную часть аргументов \"event\".
//! Доставка ставится в очередь объекта \"performer\" и выполняется только когда этот объект
//! вызывает \a PIObject::callQueuedEvents() или \a PIObject::maybeCallQueuedEvents().
//! Все типы аргументов должны быть зарегистрированы с помощью макроса \a REGISTER_VARIANT(),
//! однако многие стандартные и PIP типы уже там.
//! Возвращает \a PIObject::Connection.
#  define CONNECTU_QUEUED(src, event, dest, handler, performer)

//! \relatesalso PIObject
//! \~\brief
//! \~english Connect event \"event\" from object \"src\" to lambda-expression \"functor\".
//! \~russian Соединяет событие \"event\" объекта \"src\" к лямбда-функции \"functor\".
//! \~\details
//! \~english
//! \"event\" and \"functor\" must have the same argument list.
//! Wrap \"functor\" in () when the lambda expression is complex.
//! Returns \a PIObject::Connection.
//! \~russian
//! \"event\" и \"functor\" должны иметь одинаковый список аргументов.
//! В случае сложной лямбда-функции оберните её в ().
//! Возвращает \a PIObject::Connection.
#  define CONNECTL(src, event, functor)

//! \relatesalso PIObject
//! \deprecated
//! \~english Use \a CONNECTU() instead
//! \~russian Используйте \a CONNECTU()
//! \~\brief
//! \~english Legacy compatibility helper that connects an event to a registered handler with compile-time signature spelling.
//! \~russian Устаревший совместимый макрос, который соединяет событие с зарегистрированным обработчиком через явное указание сигнатуры.
//! \~\details
//! \~english Prefer \a CONNECTU() for new code.
//! \~russian Для нового кода предпочитайте \a CONNECTU().
#  define CONNECT0(ret, src, event, dest, handler)

//! \relatesalso PIObject
//! \deprecated
//! \~english Use \a CONNECTU() instead
//! \~russian Используйте \a CONNECTU()
//! \~\brief
//! \~english Legacy compatibility helper for a one-argument registered event or handler.
//! \~russian Устаревший совместимый макрос для зарегистрированного события или обработчика с одним аргументом.
#  define CONNECT1(ret, type0, src, event, dest, handler)

//! \relatesalso PIObject
//! \deprecated
//! \~english Use \a CONNECTU() instead
//! \~russian Используйте \a CONNECTU()
//! \~\brief
//! \~english Legacy compatibility helper for a two-argument registered event or handler.
//! \~russian Устаревший совместимый макрос для зарегистрированного события или обработчика с двумя аргументами.
#  define CONNECT2(ret, type0, type1, src, event, dest, handler)

//! \relatesalso PIObject
//! \deprecated
//! \~english Use \a CONNECTU() instead
//! \~russian Используйте \a CONNECTU()
//! \~\brief
//! \~english Legacy compatibility helper for a three-argument registered event or handler.
//! \~russian Устаревший совместимый макрос для зарегистрированного события или обработчика с тремя аргументами.
#  define CONNECT3(ret, type0, type1, type2, src, event, dest, handler)

//! \relatesalso PIObject
//! \deprecated
//! \~english Use \a CONNECTU() instead
//! \~russian Используйте \a CONNECTU()
//! \~\brief
//! \~english Legacy compatibility helper for a four-argument registered event or handler.
//! \~russian Устаревший совместимый макрос для зарегистрированного события или обработчика с четырьмя аргументами.
#  define CONNECT4(ret, type0, type1, type2, type3, src, event, dest, handler)

//! \relatesalso PIObject
//! \deprecated
//! \~english Use \a CONNECTU() instead
//! \~russian Используйте \a CONNECTU()
//! \~\brief
//! \~english Synonym of \a CONNECT0
//! \~russian Аналог \a CONNECT0
#  define CONNECT CONNECT0


//! \relatesalso PIObject
//! \deprecated
//! \~english Use \a CONNECTU() instead
//! \~russian Используйте \a CONNECTU()
//! \~\brief
//! \~english Legacy compatibility helper that skips source method verification.
//! \~russian Устаревший совместимый макрос, который пропускает проверку исходного метода.
#  define WEAK_CONNECT0(ret, src, event, dest, handler)

//! \relatesalso PIObject
//! \deprecated
//! \~english Use \a CONNECTU() instead
//! \~russian Используйте \a CONNECTU()
//! \~\brief
//! \~english Legacy compatibility helper that skips source method verification for one argument.
//! \~russian Устаревший совместимый макрос, который пропускает проверку исходного метода для случая с одним аргументом.
#  define WEAK_CONNECT1(ret, type0, src, event, dest, handler)

//! \relatesalso PIObject
//! \deprecated
//! \~english Use \a CONNECTU() instead
//! \~russian Используйте \a CONNECTU()
//! \~\brief
//! \~english Legacy compatibility helper that skips source method verification for two arguments.
//! \~russian Устаревший совместимый макрос, который пропускает проверку исходного метода для случая с двумя аргументами.
#  define WEAK_CONNECT2(ret, type0, type1, src, event, dest, handler)

//! \relatesalso PIObject
//! \deprecated
//! \~english Use \a CONNECTU() instead
//! \~russian Используйте \a CONNECTU()
//! \~\brief
//! \~english Legacy compatibility helper that skips source method verification for three arguments.
//! \~russian Устаревший совместимый макрос, который пропускает проверку исходного метода для случая с тремя аргументами.
#  define WEAK_CONNECT3(ret, type0, type1, type2, src, event, dest, handler)

//! \relatesalso PIObject
//! \deprecated
//! \~english Use \a CONNECTU() instead
//! \~russian Используйте \a CONNECTU()
//! \~\brief
//! \~english Legacy compatibility helper that skips source method verification for four arguments.
//! \~russian Устаревший совместимый макрос, который пропускает проверку исходного метода для случая с четырьмя аргументами.
#  define WEAK_CONNECT4(ret, type0, type1, type2, type3, src, event, dest, handler)

//! \relatesalso PIObject
//! \deprecated
//! \~english Use \a CONNECTU() instead
//! \~russian Используйте \a CONNECTU()
//! \~\brief
//! \~english Synonym of \a WEAK_CONNECT0
//! \~russian Аналог \a WEAK_CONNECT0
#  define WEAK_CONNECT WEAK_CONNECT0


//! \relatesalso PIObject
//! \~\brief
//! \~english Disconnect a registered event from a registered event handler.
//! \~russian Разрывает соединение зарегистрированного события с зарегистрированным обработчиком.
#  define DISCONNECT0(ret, src, event, dest, handler)

//! \relatesalso PIObject
//! \~\brief
//! \~english Disconnect a one-argument registered event from a registered event handler.
//! \~russian Разрывает соединение зарегистрированного события с одним аргументом и зарегистрированного обработчика.
#  define DISCONNECT1(ret, type0, src, event, dest, handler)

//! \relatesalso PIObject
//! \~\brief
//! \~english Disconnect a two-argument registered event from a registered event handler.
//! \~russian Разрывает соединение зарегистрированного события с двумя аргументами и зарегистрированного обработчика.
#  define DISCONNECT2(ret, type0, type1, src, event, dest, handler)

//! \relatesalso PIObject
//! \~\brief
//! \~english Disconnect a three-argument registered event from a registered event handler.
//! \~russian Разрывает соединение зарегистрированного события с тремя аргументами и зарегистрированного обработчика.
#  define DISCONNECT3(ret, type0, type1, type2, src, event, dest, handler)

//! \relatesalso PIObject
//! \~\brief
//! \~english Disconnect a four-argument registered event from a registered event handler.
//! \~russian Разрывает соединение зарегистрированного события с четырьмя аргументами и зарегистрированного обработчика.
#  define DISCONNECT4(ret, type0, type1, type2, type3, src, event, dest, handler)

//! \relatesalso PIObject
//! \~\brief
//! \~english Synonym of \a DISCONNECT0
//! \~russian Аналог \a DISCONNECT0
#  define DISCONNECT DISCONNECT0


//! \relatesalso PIObject
//! \~\brief
//! \~english Low-level helper that expands to the registered handler entry point.
//! \~russian Низкоуровневый вспомогательный макрос, который разворачивается в точку входа зарегистрированного обработчика.
#  define HANDLER(handler)


#else


#  define _PI_STR(x)  #x
#  define _PI_SSTR(x) _PI_STR(x)
#  define LOCATION    __FILE__ ":" _PI_SSTR(__LINE__)
#  ifdef CC_GCC
#	define __PTYPE(t) typename __PIVariantTypeInfo__<t>::PureType
#  else
#	define __PTYPE(t) __PIVariantTypeInfo__<t>::PureType
#  endif
#  define __VVALUE(t, v)        v.value<__PTYPE(t)>()
#  define __PIOBJECT_MAX_ARGS__ 4


#  define PIOBJECT(name)                                 \
                                                         \
  protected:                                             \
	  typedef name __PIObject__;                         \
                                                         \
  public:                                                \
	  static const char * __classNameCC() {              \
		  return #name;                                  \
	  }                                                  \
	  static uint __classNameIDS() {                     \
		  static uint ret = PIStringAscii(#name).hash(); \
		  return ret;                                    \
	  }                                                  \
	  const char * className() const override {          \
		  return #name;                                  \
	  }                                                  \
	  uint classNameID() const override {                \
		  static uint ret = PIStringAscii(#name).hash(); \
		  return ret;                                    \
	  }                                                  \
                                                         \
  private:                                               \
	  int ptrOffset() const override {                   \
		  name * o = (name *)100;                        \
		  return int(llong((PIObject *)o) - llong(o));   \
	  }                                                  \
	  class __BaseInitializer__ {                        \
	  public:                                            \
		  __BaseInitializer__() {                        \
			  uint pid = PIObject::__classNameIDS();     \
			  if (pid == 0) return;                      \
			  uint id = __classNameIDS();                \
			  PIMutexLocker ml(__meta_mutex());          \
			  if (__meta_data().contains(id)) return;    \
			  __meta_data()[pid];                        \
			  __meta_data()[id];                         \
			  __MetaData & ehp(__meta_data()[pid]);      \
			  __MetaData & eh(__meta_data()[id]);        \
			  eh.eh_set << ehp.eh_set;                   \
			  eh.eh_func << ehp.eh_func;                 \
			  eh.addScope(__classNameCC(), id);          \
		  }                                              \
	  };                                                 \
	  __BaseInitializer__ __base_init__;

#  define PIOBJECT_PARENT(name)                         \
	  class __ParentInitializer__ {                     \
	  public:                                           \
		  __ParentInitializer__() {                     \
			  uint pid = name::__classNameIDS();        \
			  if (pid == 0) return;                     \
			  uint id = __classNameIDS();               \
			  PIMutexLocker ml(__meta_mutex());         \
			  __MetaData & eh(__meta_data()[id]);       \
			  if (eh.scope_id.contains(pid)) return;    \
			  __MetaData ehp(__meta_data().value(pid)); \
			  eh.eh_set << ehp.eh_set;                  \
			  eh.eh_func << ehp.eh_func;                \
			  eh.scope_id   = ehp.scope_id;             \
			  eh.scope_list = ehp.scope_list;           \
			  eh.addScope(__classNameCC(), id);         \
		  }                                             \
	  };                                                \
	  __ParentInitializer__ __parent_init__;            \
                                                        \
  public:                                               \
	  const char * parentClassName() const override {   \
		  return #name;                                 \
	  }                                                 \
	  typedef name __Parent__;                          \
                                                        \
  private:

#  define PIOBJECT_SUBCLASS(name, parent) PIOBJECT(name) PIOBJECT_PARENT(parent)


#  define __EH_INIT_BASE__(ret, name)                   \
	  PIMutexLocker ml(__meta_mutex());                 \
	  __MetaData & eh(__meta_data()[__classNameIDS()]); \
	  if (eh.eh_set[fp]) return;                        \
	  eh.eh_set << fp;                                  \
	  __MetaFunc & f(eh.eh_func[fp]);                   \
	  f.scope = __classNameCC();                        \
	  f.__setFuncName(#name);                           \
	  f.addr     = fp;                                  \
	  f.addrV    = fpV;                                 \
	  f.type_ret = #ret;

#  define EH_INIT0(ret, name)                                        \
	  STATIC_INITIALIZER_BEGIN                                       \
		  void * fp  = (void *)(ret(*)(void *))__stat_eh_##name##__; \
		  void * fpV = fp;                                           \
		  __EH_INIT_BASE__(ret, name)                                \
	  STATIC_INITIALIZER_END

#  define EH_INIT1(ret, name, a0, n0)                                                           \
	  STATIC_INITIALIZER_BEGIN                                                                  \
		  void * fp  = (void *)(ret(*)(void *, a0))__stat_eh_##name##__;                        \
		  void * fpV = (void *)(ret(*)(void *, const PIVariantSimple &))__stat_eh_v_##name##__; \
		  __EH_INIT_BASE__(ret, name)                                                           \
		  f.__addArgument(#a0, #n0);                                                            \
	  STATIC_INITIALIZER_END

#  define EH_INIT2(ret, name, a0, n0, a1, n1)                                                                            \
	  STATIC_INITIALIZER_BEGIN                                                                                           \
		  void * fp  = (void *)(ret(*)(void *, a0, a1))__stat_eh_##name##__;                                             \
		  void * fpV = (void *)(ret(*)(void *, const PIVariantSimple &, const PIVariantSimple &))__stat_eh_v_##name##__; \
		  __EH_INIT_BASE__(ret, name)                                                                                    \
		  f.__addArgument(#a0, #n0);                                                                                     \
		  f.__addArgument(#a1, #n1);                                                                                     \
	  STATIC_INITIALIZER_END

#  define EH_INIT3(ret, name, a0, n0, a1, n1, a2, n2)                                                                                    \
	  STATIC_INITIALIZER_BEGIN                                                                                                           \
		  void * fp = (void *)(ret(*)(void *, a0, a1, a2))__stat_eh_##name##__;                                                          \
		  void * fpV =                                                                                                                   \
			  (void *)(ret(*)(void *, const PIVariantSimple &, const PIVariantSimple &, const PIVariantSimple &))__stat_eh_v_##name##__; \
		  __EH_INIT_BASE__(ret, name)                                                                                                    \
		  f.__addArgument(#a0, #n0);                                                                                                     \
		  f.__addArgument(#a1, #n1);                                                                                                     \
		  f.__addArgument(#a2, #n2);                                                                                                     \
	  STATIC_INITIALIZER_END

#  define EH_INIT4(ret, name, a0, n0, a1, n1, a2, n2, a3, n3)                                                                              \
	  STATIC_INITIALIZER_BEGIN                                                                                                             \
		  void * fp = (void *)(ret(*)(void *, a0, a1, a2, a3))__stat_eh_##name##__;                                                        \
		  void * fpV =                                                                                                                     \
			  (void *)(ret(*)(void *, const PIVariantSimple &, const PIVariantSimple &, const PIVariantSimple &, const PIVariantSimple &)) \
				  __stat_eh_v_##name##__;                                                                                                  \
		  __EH_INIT_BASE__(ret, name)                                                                                                      \
		  f.__addArgument(#a0, #n0);                                                                                                       \
		  f.__addArgument(#a1, #n1);                                                                                                       \
		  f.__addArgument(#a2, #n2);                                                                                                       \
		  f.__addArgument(#a3, #n3);                                                                                                       \
	  STATIC_INITIALIZER_END


#  define EVENT_HANDLER0(ret, name)                   \
	  EH_INIT0(ret, name)                             \
	  static ret __stat_eh_##name##__(void * __o__) { \
		  return ((__PIObject__ *)__o__)->name();     \
	  }                                               \
	  ret name()

#  define EVENT_HANDLER1(ret, name, a0, n0)                                         \
	  EH_INIT1(ret, name, a0, n0)                                                   \
	  static ret __stat_eh_##name##__(void * __o__, a0 n0) {                        \
		  return ((__PIObject__ *)__o__)->name(n0);                                 \
	  }                                                                             \
	  static ret __stat_eh_v_##name##__(void * __o__, const PIVariantSimple & v0) { \
		  __PTYPE(a0) tv0 = __VVALUE(a0, v0);                                       \
		  return ((__PIObject__ *)__o__)->name(tv0);                                \
	  }                                                                             \
	  ret name(a0 n0)

#  define EVENT_HANDLER2(ret, name, a0, n0, a1, n1)                                                             \
	  EH_INIT2(ret, name, a0, n0, a1, n1)                                                                       \
	  static ret __stat_eh_##name##__(void * __o__, a0 n0, a1 n1) {                                             \
		  return ((__PIObject__ *)__o__)->name(n0, n1);                                                         \
	  }                                                                                                         \
	  static ret __stat_eh_v_##name##__(void * __o__, const PIVariantSimple & v0, const PIVariantSimple & v1) { \
		  __PTYPE(a0) tv0 = __VVALUE(a0, v0);                                                                   \
		  __PTYPE(a1) tv1 = __VVALUE(a1, v1);                                                                   \
		  return ((__PIObject__ *)__o__)->name(tv0, tv1);                                                       \
	  }                                                                                                         \
	  ret name(a0 n0, a1 n1)

#  define EVENT_HANDLER3(ret, name, a0, n0, a1, n1, a2, n2)                \
	  EH_INIT3(ret, name, a0, n0, a1, n1, a2, n2)                          \
	  static ret __stat_eh_##name##__(void * __o__, a0 n0, a1 n1, a2 n2) { \
		  return ((__PIObject__ *)__o__)->name(n0, n1, n2);                \
	  }                                                                    \
	  static ret __stat_eh_v_##name##__(void * __o__,                      \
		                                const PIVariantSimple & v0,        \
		                                const PIVariantSimple & v1,        \
		                                const PIVariantSimple & v2) {      \
		  __PTYPE(a0) tv0 = __VVALUE(a0, v0);                              \
		  __PTYPE(a1) tv1 = __VVALUE(a1, v1);                              \
		  __PTYPE(a2) tv2 = __VVALUE(a2, v2);                              \
		  return ((__PIObject__ *)__o__)->name(tv0, tv1, tv2);             \
	  }                                                                    \
	  ret name(a0 n0, a1 n1, a2 n2)

#  define EVENT_HANDLER4(ret, name, a0, n0, a1, n1, a2, n2, a3, n3)               \
	  EH_INIT4(ret, name, a0, n0, a1, n1, a2, n2, a3, n3)                         \
	  static ret __stat_eh_##name##__(void * __o__, a0 n0, a1 n1, a2 n2, a3 n3) { \
		  return ((__PIObject__ *)__o__)->name(n0, n1, n2, n3);                   \
	  }                                                                           \
	  static ret __stat_eh_v_##name##__(void * __o__,                             \
		                                const PIVariantSimple & v0,               \
		                                const PIVariantSimple & v1,               \
		                                const PIVariantSimple & v2,               \
		                                const PIVariantSimple & v3) {             \
		  __PTYPE(a0) tv0 = __VVALUE(a0, v0);                                     \
		  __PTYPE(a1) tv1 = __VVALUE(a1, v1);                                     \
		  __PTYPE(a2) tv2 = __VVALUE(a2, v2);                                     \
		  __PTYPE(a3) tv3 = __VVALUE(a3, v3);                                     \
		  return ((__PIObject__ *)__o__)->name(tv0, tv1, tv2, tv3);               \
	  }                                                                           \
	  ret name(a0 n0, a1 n1, a2 n2, a3 n3)

#  define EVENT_HANDLER EVENT_HANDLER0


#  define EVENT_VHANDLER0(ret, name)                  \
	  EH_INIT0(ret, name)                             \
	  static ret __stat_eh_##name##__(void * __o__) { \
		  return ((__PIObject__ *)__o__)->name();     \
	  }                                               \
	  virtual ret name()

#  define EVENT_VHANDLER1(ret, name, a0, n0)                                        \
	  EH_INIT1(ret, name, a0, n0)                                                   \
	  static ret __stat_eh_##name##__(void * __o__, a0 n0) {                        \
		  return ((__PIObject__ *)__o__)->name(n0);                                 \
	  }                                                                             \
	  static ret __stat_eh_v_##name##__(void * __o__, const PIVariantSimple & v0) { \
		  return ((__PIObject__ *)__o__)->name(__VVALUE(a0, v0));                   \
	  }                                                                             \
	  virtual ret name(a0 n0)

#  define EVENT_VHANDLER2(ret, name, a0, n0, a1, n1)                                                            \
	  EH_INIT2(ret, name, a0, n0, a1, n1)                                                                       \
	  static ret __stat_eh_##name##__(void * __o__, a0 n0, a1 n1) {                                             \
		  return ((__PIObject__ *)__o__)->name(n0, n1);                                                         \
	  }                                                                                                         \
	  static ret __stat_eh_v_##name##__(void * __o__, const PIVariantSimple & v0, const PIVariantSimple & v1) { \
		  return ((__PIObject__ *)__o__)->name(__VVALUE(a0, v0), __VVALUE(a1, v1));                             \
	  }                                                                                                         \
	  virtual ret name(a0 n0, a1 n1)

#  define EVENT_VHANDLER3(ret, name, a0, n0, a1, n1, a2, n2)                                          \
	  EH_INIT3(ret, name, a0, n0, a1, n1, a2, n2)                                                     \
	  static ret __stat_eh_##name##__(void * __o__, a0 n0, a1 n1, a2 n2) {                            \
		  return ((__PIObject__ *)__o__)->name(n0, n1, n2);                                           \
	  }                                                                                               \
	  static ret __stat_eh_v_##name##__(void * __o__,                                                 \
		                                const PIVariantSimple & v0,                                   \
		                                const PIVariantSimple & v1,                                   \
		                                const PIVariantSimple & v2) {                                 \
		  return ((__PIObject__ *)__o__)->name(__VVALUE(a0, v0), __VVALUE(a1, v1), __VVALUE(a2, v2)); \
	  }                                                                                               \
	  virtual ret name(a0 n0, a1 n1, a2 n2)

#  define EVENT_VHANDLER4(ret, name, a0, n0, a1, n1, a2, n2, a3, n3)                                                    \
	  EH_INIT4(ret, name, a0, n0, a1, n1, a2, n2, a3, n3)                                                               \
	  static ret __stat_eh_##name##__(void * __o__, a0 n0, a1 n1, a2 n2, a3 n3) {                                       \
		  return ((__PIObject__ *)__o__)->name(n0, n1, n2, n3);                                                         \
	  }                                                                                                                 \
	  static ret __stat_eh_v_##name##__(void * __o__,                                                                   \
		                                const PIVariantSimple & v0,                                                     \
		                                const PIVariantSimple & v1,                                                     \
		                                const PIVariantSimple & v2,                                                     \
		                                const PIVariantSimple & v3) {                                                   \
		  return ((__PIObject__ *)__o__)->name(__VVALUE(a0, v0), __VVALUE(a1, v1), __VVALUE(a2, v2), __VVALUE(a3, v3)); \
	  }                                                                                                                 \
	  virtual ret name(a0 n0, a1 n1, a2 n2, a3 n3)

#  define EVENT_VHANDLER EVENT_VHANDLER0


#  define EVENT0(name)                                   \
	  EVENT_HANDLER0(void, name) {                       \
		  static uint eid = PIStringAscii(#name).hash(); \
		  PIObject::raiseEvent(this, eid);               \
	  }

#  define EVENT1(name, a0, n0)                           \
	  EVENT_HANDLER1(void, name, a0, n0) {               \
		  static uint eid = PIStringAscii(#name).hash(); \
		  PIObject::raiseEvent(this, eid, n0);           \
	  }

#  define EVENT2(name, a0, n0, a1, n1)                   \
	  EVENT_HANDLER2(void, name, a0, n0, a1, n1) {       \
		  static uint eid = PIStringAscii(#name).hash(); \
		  PIObject::raiseEvent(this, eid, n0, n1);       \
	  }

#  define EVENT3(name, a0, n0, a1, n1, a2, n2)             \
	  EVENT_HANDLER3(void, name, a0, n0, a1, n1, a2, n2) { \
		  static uint eid = PIStringAscii(#name).hash();   \
		  PIObject::raiseEvent(this, eid, n0, n1, n2);     \
	  }

#  define EVENT4(name, a0, n0, a1, n1, a2, n2, a3, n3)             \
	  EVENT_HANDLER4(void, name, a0, n0, a1, n1, a2, n2, a3, n3) { \
		  static uint eid = PIStringAscii(#name).hash();           \
		  PIObject::raiseEvent(this, eid, n0, n1, n2, n3);         \
	  }

#  define EVENT                                    EVENT0


#  define RAISE_EVENT0(src, event)                 (src)->event();
#  define RAISE_EVENT1(src, event, v0)             (src)->event(v0);
#  define RAISE_EVENT2(src, event, v0, v1)         (src)->event(v0, v1);
#  define RAISE_EVENT3(src, event, v0, v1, v2)     (src)->event(v0, v1, v2);
#  define RAISE_EVENT4(src, event, v0, v1, v2, v3) (src)->event(v0, v1, v2, v3);
#  define RAISE_EVENT                              RAISE_EVENT0


#  define CONNECTU(src, event, dest, handler) \
	  PIObject::piConnectU(src, PIStringAscii(#event), dest, dest, PIStringAscii(#handler), LOCATION);

#  define CONNECTU_QUEUED(src, event, dest, handler, performer) \
	  PIObject::piConnectU(src, PIStringAscii(#event), dest, dest, PIStringAscii(#handler), LOCATION, performer);

#  define CONNECTL(src, event, functor) \
	  PIObject::piConnectLS(src, PIStringAscii(#event), PIObject::__newFunctor(&(src)->__stat_eh_##event##__, functor), LOCATION);


#  define CONNECT0(ret, src, event, dest, handler)                                    \
	  PIObject::piConnect(src,                                                        \
		                  PIStringAscii(#event),                                      \
		                  dest,                                                       \
		                  dest,                                                       \
		                  (void *)(ret(*)(void *))(&(dest)->__stat_eh_##handler##__), \
		                  (void *)(void (*)(void *))(&(src)->__stat_eh_##event##__),  \
		                  0,                                                          \
		                  LOCATION);

#  define CONNECT1(ret, a0, src, event, dest, handler)                                    \
	  PIObject::piConnect(src,                                                            \
		                  PIStringAscii(#event),                                          \
		                  dest,                                                           \
		                  dest,                                                           \
		                  (void *)(ret(*)(void *, a0))(&(dest)->__stat_eh_##handler##__), \
		                  (void *)(void (*)(void *, a0))(&(src)->__stat_eh_##event##__),  \
		                  1,                                                              \
		                  LOCATION);

#  define CONNECT2(ret, a0, a1, src, event, dest, handler)                                    \
	  PIObject::piConnect(src,                                                                \
		                  PIStringAscii(#event),                                              \
		                  dest,                                                               \
		                  dest,                                                               \
		                  (void *)(ret(*)(void *, a0, a1))(&(dest)->__stat_eh_##handler##__), \
		                  (void *)(void (*)(void *, a0, a1))(&(src)->__stat_eh_##event##__),  \
		                  2,                                                                  \
		                  LOCATION);

#  define CONNECT3(ret, a0, a1, a2, src, event, dest, handler)                                    \
	  PIObject::piConnect(src,                                                                    \
		                  PIStringAscii(#event),                                                  \
		                  dest,                                                                   \
		                  dest,                                                                   \
		                  (void *)(ret(*)(void *, a0, a1, a2))(&(dest)->__stat_eh_##handler##__), \
		                  (void *)(void (*)(void *, a0, a1, a2))(&(src)->__stat_eh_##event##__),  \
		                  3,                                                                      \
		                  LOCATION);

#  define CONNECT4(ret, a0, a1, a2, a3, src, event, dest, handler)                                    \
	  PIObject::piConnect(src,                                                                        \
		                  PIStringAscii(#event),                                                      \
		                  dest,                                                                       \
		                  dest,                                                                       \
		                  (void *)(ret(*)(void *, a0, a1, a2, a3))(&(dest)->__stat_eh_##handler##__), \
		                  (void *)(void (*)(void *, a0, a1, a2, a3))(&(src)->__stat_eh_##event##__),  \
		                  4,                                                                          \
		                  LOCATION);

#  define CONNECT CONNECT0


#  define WEAK_CONNECT0(ret, src, event, dest, handler)                               \
	  PIObject::piConnect(src,                                                        \
		                  PIStringAscii(#event),                                      \
		                  dest,                                                       \
		                  dest,                                                       \
		                  (void *)(ret(*)(void *))(&(dest)->__stat_eh_##handler##__), \
		                  0,                                                          \
		                  0,                                                          \
		                  LOCATION);

#  define WEAK_CONNECT1(ret, a0, src, event, dest, handler)                               \
	  PIObject::piConnect(src,                                                            \
		                  PIStringAscii(#event),                                          \
		                  dest,                                                           \
		                  dest,                                                           \
		                  (void *)(ret(*)(void *, a0))(&(dest)->__stat_eh_##handler##__), \
		                  0,                                                              \
		                  1,                                                              \
		                  LOCATION);

#  define WEAK_CONNECT2(ret, a0, a1, src, event, dest, handler)                               \
	  PIObject::piConnect(src,                                                                \
		                  PIStringAscii(#event),                                              \
		                  dest,                                                               \
		                  dest,                                                               \
		                  (void *)(ret(*)(void *, a0, a1))(&(dest)->__stat_eh_##handler##__), \
		                  0,                                                                  \
		                  2,                                                                  \
		                  LOCATION);

#  define WEAK_CONNECT3(ret, a0, a1, a2, src, event, dest, handler)                               \
	  PIObject::piConnect(src,                                                                    \
		                  PIStringAscii(#event),                                                  \
		                  dest,                                                                   \
		                  dest,                                                                   \
		                  (void *)(ret(*)(void *, a0, a1, a2))(&(dest)->__stat_eh_##handler##__), \
		                  0,                                                                      \
		                  3,                                                                      \
		                  LOCATION);

#  define WEAK_CONNECT4(ret, a0, a1, a2, a3, src, event, dest, handler)                               \
	  PIObject::piConnect(src,                                                                        \
		                  PIStringAscii(#event),                                                      \
		                  dest,                                                                       \
		                  dest,                                                                       \
		                  (void *)(ret(*)(void *, a0, a1, a2, a3))(&(dest)->__stat_eh_##handler##__), \
		                  0,                                                                          \
		                  4,                                                                          \
		                  LOCATION);

#  define WEAK_CONNECT WEAK_CONNECT0


#  define DISCONNECT0(ret, src, event, dest, handler) \
	  PIObject::piDisconnect(src, PIStringAscii(#event), dest, (void *)(ret(*)(void *))(&(dest)->__stat_eh_##handler##__));

#  define DISCONNECT1(ret, a0, src, event, dest, handler) \
	  PIObject::piDisconnect(src, PIStringAscii(#event), dest, (void *)(ret(*)(void *, a0))(&(dest)->__stat_eh_##handler##__));

#  define DISCONNECT2(ret, a0, a1, src, event, dest, handler) \
	  PIObject::piDisconnect(src, PIStringAscii(#event), dest, (void *)(ret(*)(void *, a0, a1))(&(dest)->__stat_eh_##handler##__));

#  define DISCONNECT3(ret, a0, a1, a2, src, event, dest, handler) \
	  PIObject::piDisconnect(src, PIStringAscii(#event), dest, (void *)(ret(*)(void *, a0, a1, a2))(&(dest)->__stat_eh_##handler##__));

#  define DISCONNECT4(ret, a0, a1, a2, a3, src, event, dest, handler) \
	  PIObject::piDisconnect(src, PIStringAscii(#event), dest, (void *)(ret(*)(void *, a0, a1, a2, a3))(&(dest)->__stat_eh_##handler##__));

#  define DISCONNECT             DISCONNECT0


#  define HANDLER(handler)       __stat_eh_##handler##__

#  define __PIOBJECT_SIGNATURE__ 0xabcdbadc


#endif


#endif // PIOBJECT_MACROS_H
