00001 #ifndef __UPF_CXX_H__
00002 #define __UPF_CXX_H__
00003
00009 #include <stdio.h>
00010 #include <upf/abi.h>
00011 #include <string>
00012 #include <vector>
00013
00014 namespace upf
00015 {
00016 typedef upf_InterfaceData InterfacePtr;
00017 typedef upf_IID IID;
00018 }
00019
00020 inline bool operator==(const ::upf::IID& id1, const ::upf::IID& id2)
00021 {
00022 return id1.data1 == id2.data1 && id1.data2 == id2.data2 &&
00023 id1.data3 == id2.data3 && id1.data4 == id2.data4 &&
00024 id1.version_major == id2.version_major &&
00025 id1.version_minor == id2.version_minor;
00026 }
00027
00028 inline bool operator!=(const ::upf::IID& id1, const ::upf::IID& id2)
00029 {
00030 return !(id1 == id2);
00031 }
00032
00033
00034 namespace upf {
00035
00036 class IObject;
00037 class IManager;
00038 class IWriteableClassInfo;
00039
00040 template<class T> class Ptr;
00041
00042
00043
00044
00045
00046 template<class T> struct InterfaceTraits;
00047
00048
00049 enum MultiPurposeHookMode
00050 {
00051 _UPF_HOOK_MODE_INIT_CLASSINFO = 1,
00052 _UPF_HOOK_MODE_QUERY_INTERFACE = 2
00053 };
00054
00055
00056
00057 struct IWriteableClassInfoWrapper
00058 {
00059 virtual void addInterface(const IID& iid) = 0;
00060 };
00061 template<class T>
00062 struct IWriteableClassInfoWrapperImpl : public IWriteableClassInfoWrapper
00063 {
00064 IWriteableClassInfoWrapperImpl(T *t) : m_t(t) {}
00065 void addInterface(const IID& iid) { m_t->addInterface(iid); }
00066 T *m_t;
00067 };
00068
00069
00070 struct MultiPurposeHookArgs
00071 {
00072 MultiPurposeHookMode mode;
00073 union
00074 {
00075 struct
00076 {
00077 IWriteableClassInfo *ci;
00078 IWriteableClassInfoWrapper *ciWrapper;
00079 } ici;
00080 struct
00081 {
00082 const IID* iid;
00083 InterfacePtr retval;
00084 } qi;
00085 } u;
00086 };
00087
00088
00089
00090 class CxxBase
00091 {
00092 public:
00093 virtual upf_Object* _upf_getABIObject() = 0;
00094 };
00095
00096 template<class T> class Proxy;
00097
00098
00099 inline bool checkIID(const IID& requested, const IID& available)
00100 {
00101 return UPF_CHECK_IID(requested, available);
00102 }
00103
00104 template<class T> inline T* _makeCxxObject(upf_Object *object)
00105 {
00106 if (object == NULL)
00107 return NULL;
00108 upf_InterfaceData i;
00109 object->queryInterface(object, &InterfaceTraits<T>::iid(), &i);
00110 if (object->nativeContext == upf_context)
00111 {
00112 return static_cast<T*>(i.data);
00113 }
00114 else
00115 {
00116 if (i.data == NULL)
00117 return NULL;
00118 else
00119 return new Proxy<T>(object, i);
00120 }
00121 }
00122
00123
00124
00125
00126
00127
00128
00129
00130 template<typename T>
00131 void _UPF_CALLING_CONVENTION _CxxABIQueryInterface(T *object, const upf_IID *iid,
00132 upf_InterfaceData *retval)
00133 {
00134 *retval = (static_cast<IObject*>(object->data))->queryInterface(*iid);
00135 }
00136
00137
00138
00145 template<class T> inline T* queryInterface(IObject *obj)
00146 {
00147 if (obj == NULL)
00148 return NULL;
00149 else
00150 {
00151 InterfacePtr i = obj->queryInterface(InterfaceTraits<T>::iid());
00152 upf_Object *abi = obj->_upf_getABIObject();
00153 if (abi->nativeContext == upf_context)
00154 {
00155 return reinterpret_cast<T*>(i.data);
00156 }
00157 else
00158 {
00159 if (i.data == NULL)
00160 return NULL;
00161 else
00162 return new Proxy<T>(abi, i);
00163 }
00164 }
00165 }
00166
00167
00168
00169
00170
00171
00172
00173 #define _UPF_DECLARE_CLASS_NO_FRIENDS(classname) \
00174 private:\
00175 typedef classname _upfClassType; \
00176 upf_Object _upf_object; \
00177 static void _upfMultiPurposeHook(::upf::MultiPurposeHookArgs *data, classname *instance); \
00178 static void _upf_initClass(::upf::IWriteableClassInfo *classinfo); \
00179 static ::upf::CID _upf_getCID(); \
00180 void _upf_initInstance(); \
00181 public: \
00182 upf_Object* _upf_getABIObject() { return &_upf_object; } \
00183 void incRef(); \
00184 void decRef(); \
00185 ::upf::InterfacePtr queryInterface(const ::upf::IID& iface); \
00186 ::upf::CID getClassID();
00187
00188
00189 #ifdef _MSC_VER
00190 #define _UPF_DECLARE_CLASS_FRIENDS_DECL(classname) \
00191 friend class ::upf::StdFactory< classname >; \
00192 friend class ::upf::ClassRegistrator< classname >;
00193 #else
00194 #define _UPF_DECLARE_CLASS_FRIENDS_DECL(classname) \
00195 typedef ::upf::StdFactory< classname > _upfFactory; \
00196 typedef ::upf::ClassRegistrator< classname > _upfRegistrator; \
00197 friend class _upfFactory; \
00198 friend class _upfRegistrator;
00199 #endif
00200
00218 #define UPF_DECLARE_CLASS(classname) \
00219 _UPF_DECLARE_CLASS_FRIENDS_DECL(classname) \
00220 _UPF_DECLARE_CLASS_NO_FRIENDS(classname)
00221
00222
00223 #define _UPF_DO_IMPLEMENT_CLASS(classname, prefix) \
00224 prefix void classname::incRef() \
00225 { \
00226 _upf_object.refCnt++; \
00227 } \
00228 prefix void classname::decRef() \
00229 { \
00230 if (--_upf_object.refCnt == 0) \
00231 { \
00232 delete this; \
00233 } \
00234 } \
00235 prefix ::upf::InterfacePtr classname::queryInterface(const ::upf::IID& iface) \
00236 { \
00237 ::upf::MultiPurposeHookArgs data; \
00238 data.mode = ::upf::_UPF_HOOK_MODE_QUERY_INTERFACE; \
00239 data.u.qi.iid = &iface; \
00240 data.u.qi.retval.data = NULL; \
00241 _upfMultiPurposeHook(&data, this); \
00242 return data.u.qi.retval; \
00243 } \
00244 prefix void classname::_upf_initInstance() \
00245 { \
00246 _upf_object.refCnt = 0; \
00247 _upf_object.data = static_cast< ::upf::IObject* >(this); \
00248 _upf_object.nativeContext = upf_context; \
00249 _upf_object.queryInterface = ::upf::_CxxABIQueryInterface; \
00250 } \
00251 prefix void classname::_upf_initClass(::upf::IWriteableClassInfo *classinfo) \
00252 { \
00253 if (classinfo == NULL) return; \
00254 ::upf::MultiPurposeHookArgs data; \
00255 ::upf::IWriteableClassInfoWrapperImpl< ::upf::IWriteableClassInfo > wrapper(classinfo); \
00256 data.mode = ::upf::_UPF_HOOK_MODE_INIT_CLASSINFO; \
00257 data.u.ici.ci = classinfo; \
00258 data.u.ici.ciWrapper = &wrapper; \
00259 classinfo->setCID(_upf_getCID()); \
00260 _upfMultiPurposeHook(&data, NULL); \
00261 } \
00262 prefix ::upf::CID classname::_upf_getCID() \
00263 { \
00264 static ::upf::CID my_cid = 0; \
00265 if (my_cid == 0) \
00266 my_cid = upf_middleware->funcs.alloc_new_cid(); \
00267 return my_cid; \
00268 } \
00269 prefix ::upf::CID classname::getClassID() \
00270 { \
00271 return _upf_getCID(); \
00272 } \
00273 prefix void classname::_upfMultiPurposeHook(::upf::MultiPurposeHookArgs* data, classname *instance)
00274
00275
00282 #define UPF_INTERFACE(iface) \
00283 if (::upf::InterfaceTraits< iface >::query(instance, data)) return;
00284
00285
00292 #define UPF_PROPERTY(name, value) \
00293 if (data->mode == ::upf::_UPF_HOOK_MODE_INIT_CLASSINFO) \
00294 data->u.ici.ci->addProperty(name, value);
00295
00296
00311 #define UPF_REQUIRES_CLASS(classname)
00312
00313
00314 #define _UPF_NOTHING
00315
00337 #define UPF_IMPLEMENT_CLASS(classname) _UPF_DO_IMPLEMENT_CLASS(classname, _UPF_NOTHING)
00338
00339
00340
00341
00342
00356 #define UPF_REGISTER_CLASS(classname) \
00357 ::upf::ClassRegistrator< classname >::registerClass( #classname )
00358
00359 #ifndef UPF_BUILDING_MODULE
00360
00381 #define UPF_DLL_MODULE() \
00382 const char * _UPF_ERROR = You_must_define_UPF_BUILDING_MODULE_macro_on_your_command_line;
00383 #else
00384 #define UPF_DLL_MODULE() \
00385 upf_middlewareLayer *upf_middleware; \
00386 upf_ContextID __upf_module_context; \
00387 static void __upf_DllEntryPointImpl(int action, int *retval); \
00388 _UPF_ALWAYS_EXPORTED_SYMBOL int _UPF_CALLING_CONVENTION \
00389 _UPF_DLL_ENTRY_POINT(upf_middlewareLayer *middleware, \
00390 int action) \
00391 { \
00392 if (!UPF_CHECK_ABI_VERSION(middleware->ABI_version)) \
00393 return 0; \
00394 if (action == _UPF_DLL_ACTION_LOAD) \
00395 { \
00396 upf_middleware = middleware; \
00397 __upf_module_context = \
00398 middleware->funcs.get_context(UPF_RUNTIME_CONTEXT); \
00399 } \
00400 int retval = 1; \
00401 __upf_DllEntryPointImpl(action, &retval); \
00402 return retval; \
00403 } \
00404 static void __upf_DllEntryPointImpl(int action, int *retval)
00405
00406
00407 #endif
00408
00417 #define UPF_EXPORTED_CLASS(classname) \
00418 if (action == _UPF_DLL_ACTION_INIT_CLASSES) \
00419 { UPF_REGISTER_CLASS(classname); }
00420
00421
00422
00423
00424 template<typename T> inline bool _initFunctionCaller(T (*func)());
00425 template<> inline bool _initFunctionCaller<bool>(bool (*func)())
00426 { return func(); }
00427 template<> inline bool _initFunctionCaller<void>(void (*func)())
00428 { func(); return true; }
00429
00430
00443 #define UPF_ON_LOAD(func) \
00444 if (action == _UPF_DLL_ACTION_LOAD && \
00445 !::upf::_initFunctionCaller(func)) { *retval = 0; return; }
00446
00457 #define UPF_ON_UNLOAD(func) \
00458 if (action == _UPF_DLL_ACTION_UNLOAD && \
00459 !::upf::_initFunctionCaller(func)) { *retval = 0; return; }
00460
00461 };
00462
00463
00464 #endif