Main Page   Namespace List   Class Hierarchy   Alphabetical List   Compound List   File List   Namespace Members   Compound Members   File Members   Related Pages  

cxx.h

Go to the documentation of this file.
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; // fwd reference
00041 
00042 // ----------------------------------------------------------------------------
00043 // Helpers:
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 // This is a dirty hack neccessary because some compilers (MSVC, as usual)
00056 // can't do partial template specialization
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 // NB: this is yet another dirty hack. We don't need to make this function
00124 //     a template because we will only use it for T=upf_Object. But it can't
00125 //     be regular inlined function because calling convention can't be specified
00126 //     for inline functions in win32 compilers. The function can't be non-inline,
00127 //     either, because gcc would require implementation file then and we want to
00128 //     avoid having to link against C++ library at any cost because of binary
00129 //     incompability.
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 // upf implementation-side API:
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 // Visual C++ 6 is either too old to implement ISO C++ or it ignores it:
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     // FIXME -- TODO
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 // This trait class makes it possible to use both functions returning
00423 // bool and void as onLoad/onUnload functions:
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 }; // end of namespace 'upf'
00462 
00463 
00464 #endif

Generated on Wed Jan 15 23:10:55 2003 for Universal Plugins Framework by doxygen1.2.18