|
scf.h00001 /* 00002 Crystal Space Shared Class Facility (SCF) 00003 Copyright (C) 1999 by Andrew Zabolotny 00004 00005 This library is free software; you can redistribute it and/or 00006 modify it under the terms of the GNU Library General Public 00007 License as published by the Free Software Foundation; either 00008 version 2 of the License, or (at your option) any later version. 00009 00010 This library is distributed in the hope that it will be useful, 00011 but WITHOUT ANY WARRANTY; without even the implied warranty of 00012 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 00013 Library General Public License for more details. 00014 00015 You should have received a copy of the GNU Library General Public 00016 License along with this library; if not, write to the Free 00017 Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. 00018 */ 00019 00020 #ifndef __CSSCF_H__ 00021 #define __CSSCF_H__ 00022 00023 /* 00024 PLEASE USE 8-SPACE TAB WIDTH WHEN EDITING THIS FILE! 00025 */ 00026 00030 typedef uint32 scfInterfaceID; 00031 00036 #ifdef SCF_DEBUG 00037 # define SCF_TRACE(x) \ 00038 { \ 00039 printf ("SCF [%s:%d]:\n", __FILE__, __LINE__); \ 00040 printf x; SCF_PRINT_CALL_ADDRESS \ 00041 } 00042 #else 00043 # define SCF_TRACE(x) 00044 #endif 00045 00050 #if (__GNUC__ >= 2) && (__GNUC_MINOR__ >= 8) 00051 # define SCF_PRINT_CALL_ADDRESS \ 00052 printf (" Called from address %p\n", __builtin_return_address (0)); 00053 #else 00054 # define SCF_PRINT_CALL_ADDRESS 00055 #endif 00056 00058 #define SCF_CONSTRUCT_VERSION(Major,Minor,Micro) \ 00059 ((Major << 24) | (Minor << 16) | Micro) 00060 00073 #define SCF_VERSION(Name,Major,Minor,Micro) \ 00074 const int VERSION_##Name = SCF_CONSTRUCT_VERSION (Major, Minor, Micro) 00075 00076 SCF_VERSION (iBase, 0, 1, 0); 00077 00083 struct iBase 00084 { 00086 virtual void IncRef () = 0; 00088 virtual void DecRef () = 0; 00090 virtual int GetRefCount () = 0; 00092 virtual void *QueryInterface (scfInterfaceID iInterfaceID, int iVersion) = 0; 00097 static void* QueryInterfaceSafe (iBase* ibase, scfInterfaceID iInterfaceID, 00098 int iVersion) 00099 { 00100 if (ibase == NULL) return NULL; 00101 else return ibase->QueryInterface (iInterfaceID, iVersion); 00102 } 00103 }; 00104 00106 #define SCF_INC_REF(ptr) {if (ptr) {ptr->IncRef();}} 00107 00109 #define SCF_DEC_REF(ptr) {if (ptr) {ptr->DecRef();}} 00110 00116 #define SCF_SET_REF(var,ref) \ 00117 { \ 00118 if (ref) ref->IncRef (); \ 00119 if (var) var->DecRef (); \ 00120 var = ref; \ 00121 } 00122 00127 #define SCF_DECLARE_IBASE \ 00128 int scfRefCount; /* Reference counter */ \ 00129 SCF_DECLARE_EMBEDDED_IBASE (iBase) 00130 00135 #define SCF_DECLARE_EMBEDDED_IBASE(OuterClass) \ 00136 public: \ 00137 OuterClass *scfParent; /* The parent object */ \ 00138 virtual void IncRef (); \ 00139 virtual void DecRef (); \ 00140 virtual int GetRefCount (); \ 00141 virtual void *QueryInterface (scfInterfaceID iInterfaceID, int iVersion) 00142 00151 #define SCF_CONSTRUCT_IBASE(Parent) \ 00152 scfRefCount = 1; scfParent = Parent; if (scfParent) scfParent->IncRef(); 00153 00161 #define SCF_CONSTRUCT_EMBEDDED_IBASE(Interface) \ 00162 Interface.scfParent = this; 00163 00169 #define SCF_IMPLEMENT_IBASE_INCREF(Class) \ 00170 void Class::IncRef () \ 00171 { \ 00172 SCF_TRACE ((" (%s *)%p->IncRef (%d)\n", #Class, this, scfRefCount + 1));\ 00173 scfRefCount++; \ 00174 } 00175 00181 #define SCF_IMPLEMENT_IBASE_DECREF(Class) \ 00182 void Class::DecRef () \ 00183 { \ 00184 scfRefCount--; \ 00185 if (scfRefCount <= 0) \ 00186 { \ 00187 SCF_TRACE ((" delete (%s *)%p\n", #Class, this)); \ 00188 if (scfParent) \ 00189 scfParent->DecRef (); \ 00190 delete this; \ 00191 } \ 00192 else \ 00193 SCF_TRACE ((" (%s *)%p->DecRef (%d)\n", #Class, this, scfRefCount));\ 00194 } 00195 00200 #define SCF_IMPLEMENT_IBASE_GETREFCOUNT(Class) \ 00201 int Class::GetRefCount () \ 00202 { \ 00203 return scfRefCount; \ 00204 } 00205 00212 #define SCF_IMPLEMENT_IBASE_QUERY(Class) \ 00213 void *Class::QueryInterface (scfInterfaceID iInterfaceID, int iVersion) \ 00214 { \ 00215 SCF_TRACE ((" (%s *)%p->QueryInterface (%u, %08X)\n", \ 00216 #Class, this, iInterfaceID, iVersion)); 00217 00224 #define SCF_IMPLEMENT_IBASE_QUERY_END \ 00225 return scfParent ? \ 00226 scfParent->QueryInterface (iInterfaceID, iVersion) : NULL; \ 00227 } 00228 00234 #define SCF_IMPLEMENT_IBASE(Class) \ 00235 SCF_IMPLEMENT_IBASE_INCREF(Class) \ 00236 SCF_IMPLEMENT_IBASE_DECREF(Class) \ 00237 SCF_IMPLEMENT_IBASE_GETREFCOUNT(Class) \ 00238 SCF_IMPLEMENT_IBASE_QUERY(Class) 00239 00244 #define SCF_IMPLEMENT_IBASE_END \ 00245 SCF_IMPLEMENT_IBASE_QUERY_END 00246 00253 #define SCF_IMPLEMENT_EMBEDDED_IBASE_INCREF(Class) \ 00254 void Class::IncRef () \ 00255 { \ 00256 SCF_TRACE ((" (%s *)%p->IncRef (%d)\n", #Class, this, \ 00257 scfParent->GetRefCount () + 1)); \ 00258 scfParent->IncRef (); \ 00259 } 00260 00267 #define SCF_IMPLEMENT_EMBEDDED_IBASE_DECREF(Class) \ 00268 void Class::DecRef () \ 00269 { \ 00270 SCF_TRACE ((" (%s *)%p->DecRef (%d)\n", #Class, this, \ 00271 scfParent->GetRefCount ()-1)); \ 00272 scfParent->DecRef (); \ 00273 } 00274 00279 #define SCF_IMPLEMENT_EMBEDDED_IBASE_GETREFCOUNT(Class) \ 00280 int Class::GetRefCount () \ 00281 { \ 00282 return scfParent->GetRefCount (); \ 00283 } 00284 00291 #define SCF_IMPLEMENT_EMBEDDED_IBASE_QUERY(Class) \ 00292 void *Class::QueryInterface (scfInterfaceID iInterfaceID, int iVersion) \ 00293 { \ 00294 SCF_TRACE ((" (%s *)%p->QueryInterface (%u, %08X)\n", \ 00295 #Class, this, iInterfaceID, iVersion)); 00296 00303 #define SCF_IMPLEMENT_EMBEDDED_IBASE_QUERY_END \ 00304 return scfParent->QueryInterface (iInterfaceID, iVersion); \ 00305 } 00306 00313 #define SCF_IMPLEMENT_EMBEDDED_IBASE(Class) \ 00314 SCF_IMPLEMENT_EMBEDDED_IBASE_INCREF(Class) \ 00315 SCF_IMPLEMENT_EMBEDDED_IBASE_DECREF(Class) \ 00316 SCF_IMPLEMENT_EMBEDDED_IBASE_GETREFCOUNT(Class) \ 00317 SCF_IMPLEMENT_EMBEDDED_IBASE_QUERY(Class) 00318 00323 #define SCF_IMPLEMENT_EMBEDDED_IBASE_END \ 00324 SCF_IMPLEMENT_EMBEDDED_IBASE_QUERY_END 00325 00332 #define SCF_IMPLEMENTS_INTERFACE(Interface) \ 00333 SCF_IMPLEMENTS_INTERFACE_COMMON (Interface, this) 00334 00339 #define SCF_IMPLEMENTS_EMBEDDED_INTERFACE(Interface) \ 00340 SCF_IMPLEMENTS_INTERFACE_COMMON (Interface, (&scf##Interface)) 00341 00345 #define SCF_IMPLEMENTS_INTERFACE_COMMON(Interface,Object) \ 00346 static scfInterfaceID scfID_##Interface = (scfInterfaceID)-1; \ 00347 if (scfID_##Interface == (scfInterfaceID)-1) \ 00348 scfID_##Interface = iSCF::SCF->GetInterfaceID (#Interface); \ 00349 if (iInterfaceID == scfID_##Interface && \ 00350 scfCompatibleVersion (iVersion, VERSION_##Interface)) \ 00351 { \ 00352 (Object)->IncRef (); \ 00353 return STATIC_CAST(Interface*, Object); \ 00354 } 00355 00366 #define SCF_DECLARE_IBASE_EXT(ParentClass) \ 00367 typedef ParentClass __scf_superclass; \ 00368 virtual void IncRef (); \ 00369 virtual void DecRef (); \ 00370 virtual int GetRefCount (); \ 00371 virtual void *QueryInterface (scfInterfaceID iInterfaceID, int iVersion) 00372 00379 #define SCF_IMPLEMENT_IBASE_EXT_INCREF(Class) \ 00380 void Class::IncRef () \ 00381 { \ 00382 __scf_superclass::IncRef (); \ 00383 } 00384 00391 #define SCF_IMPLEMENT_IBASE_EXT_DECREF(Class) \ 00392 void Class::DecRef () \ 00393 { \ 00394 __scf_superclass::DecRef (); \ 00395 } 00396 00403 #define SCF_IMPLEMENT_IBASE_EXT_GETREFCOUNT(Class) \ 00404 int Class::GetRefCount () \ 00405 { \ 00406 return __scf_superclass::GetRefCount (); \ 00407 } 00408 00415 #define SCF_IMPLEMENT_IBASE_EXT_QUERY(Class) \ 00416 void *Class::QueryInterface (scfInterfaceID iInterfaceID, int iVersion) \ 00417 { 00418 00425 #define SCF_IMPLEMENT_IBASE_EXT_QUERY_END \ 00426 return __scf_superclass::QueryInterface (iInterfaceID, iVersion); \ 00427 } 00428 00433 #define SCF_IMPLEMENT_IBASE_EXT(Class) \ 00434 SCF_IMPLEMENT_IBASE_EXT_INCREF(Class) \ 00435 SCF_IMPLEMENT_IBASE_EXT_DECREF(Class) \ 00436 SCF_IMPLEMENT_IBASE_EXT_GETREFCOUNT(Class) \ 00437 SCF_IMPLEMENT_IBASE_EXT_QUERY(Class) 00438 00443 #define SCF_IMPLEMENT_IBASE_EXT_END \ 00444 SCF_IMPLEMENT_IBASE_EXT_QUERY_END 00445 00452 #define SCF_IMPLEMENT_FACTORY(Class) \ 00453 void *Create_##Class (iBase *iParent) \ 00454 { \ 00455 void *ret = new Class (iParent); \ 00456 SCF_TRACE ((" %p = new %s ()\n", ret, #Class)); \ 00457 return ret; \ 00458 } 00459 00464 #define SCF_DECLARE_FACTORY(Class) void *Create_##Class (iBase *iParent); 00465 00471 struct scfClassInfo 00472 { 00474 char *ClassID; 00476 char *Description; 00482 char *Dependencies; 00484 void *(*Factory) (iBase *iParent); 00485 }; 00486 00487 /* 00488 * The following set of macros are used to define the table that contains 00489 * information about all classes exported from a shared library. This table 00490 * is used with both static and dynamic class linking. 00491 */ 00492 00508 // extern CS_DECLARE_STATIC_VARIABLE_CLEANUP 00509 #define SCF_EXPORT_CLASS_TABLE(LibraryName) \ 00510 CS_DECLARE_STATIC_VARIABLE_CLEANUP \ 00511 CS_EXPORTED_FUNCTION void \ 00512 CS_EXPORTED_NAME(LibraryName,_scfFinalize)() \ 00513 { CS_STATIC_VARIABLE_CLEANUP } \ 00514 static inline void \ 00515 CS_EXPORTED_NAME(LibraryName,_scfUnitInitialize)(iSCF *SCF) \ 00516 { iSCF::SCF = SCF; } \ 00517 CS_EXPORTED_FUNCTION scfClassInfo* \ 00518 CS_EXPORTED_NAME(LibraryName,_scfInitialize)(iSCF *SCF) \ 00519 { \ 00520 CS_EXPORTED_NAME(LibraryName,_scfUnitInitialize)(SCF); \ 00521 static scfClassInfo ExportClassTable [] = \ 00522 { 00523 00525 #define SCF_EXPORT_CLASS(Class, ClassID, Description) \ 00526 { ClassID, Description, NULL, Create_##Class }, 00527 00529 #define SCF_EXPORT_CLASS_DEP(Class, ClassID, Description, Dependencies) \ 00530 { ClassID, Description, Dependencies, Create_##Class }, 00531 00533 #define SCF_EXPORT_CLASS_TABLE_END \ 00534 { 0, 0, 0, 0 } \ 00535 }; \ 00536 return ExportClassTable; \ 00537 } 00538 00546 #define SCF_REGISTER_STATIC_LIBRARY(LibraryName) \ 00547 extern "C" scfClassInfo *LibraryName##_scfInitialize (iSCF*); \ 00548 class __##LibraryName##_Init \ 00549 { \ 00550 public: \ 00551 __##LibraryName##_Init () \ 00552 { if (!iSCF::SCF) scfInitialize (); \ 00553 iSCF::SCF->RegisterClassList(LibraryName##_scfInitialize(iSCF::SCF)); }\ 00554 } __##LibraryName##_dummy; 00555 00561 #define SCF_REGISTER_STATIC_CLASS(Class,ClassID,Description) \ 00562 SCF_REGISTER_STATIC_CLASS_DEP (Class,ClassID,Description,NULL); 00563 00568 #define SCF_REGISTER_STATIC_CLASS_DEP(Class,ClassID,Description,Dependency)\ 00569 extern void *Create_##Class (iBase *); \ 00570 static scfClassInfo Class##_ClassInfo = \ 00571 { ClassID, Description, Dependency, Create_##Class }; \ 00572 class __##Class##_Init \ 00573 { \ 00574 public: \ 00575 __##Class##_Init () \ 00576 { if (!iSCF::SCF) scfInitialize (); \ 00577 iSCF::SCF->RegisterStaticClass (&Class##_ClassInfo); } \ 00578 } __##Class##_dummy; 00579 00580 //--------------------------------------------- Class factory interface -----// 00581 00582 SCF_VERSION (iFactory, 0, 0, 1); 00583 00596 struct iFactory : public iBase 00597 { 00599 virtual void *CreateInstance () = 0; 00601 virtual void TryUnload () = 0; 00603 virtual const char *QueryDescription () = 0; 00605 virtual const char *QueryDependencies () = 0; 00607 virtual const char *QueryClassID () = 0; 00608 }; 00609 00610 //----------------------------------------------- Client-side functions -----// 00611 00612 struct iConfigFile; 00613 struct iStrVector; 00614 00621 #define SCF_DECLARE_FAST_INTERFACE(Interface) \ 00622 inline static scfInterfaceID scfGetID_##Interface () \ 00623 { \ 00624 static scfInterfaceID ID = (scfInterfaceID)-1; \ 00625 if (ID == (scfInterfaceID)(-1)) \ 00626 ID = iSCF::SCF->GetInterfaceID (#Interface); \ 00627 return ID; \ 00628 } 00629 00634 #define SCF_CREATE_INSTANCE(ClassID,Interface) \ 00635 (Interface *)iSCF::SCF->CreateInstance ( \ 00636 ClassID, #Interface, VERSION_##Interface) 00637 00642 #define SCF_QUERY_INTERFACE(Object,Interface) \ 00643 (Interface *)(Object)->QueryInterface ( \ 00644 iSCF::SCF->GetInterfaceID (#Interface), VERSION_##Interface) 00645 00653 #define SCF_QUERY_INTERFACE_FAST(Object,Interface) \ 00654 (Interface*)(Object)->QueryInterface ( \ 00655 scfGetID_##Interface (), VERSION_##Interface) 00656 00662 #define SCF_QUERY_INTERFACE_SAFE(Object,Interface) \ 00663 (Interface *)(iBase::QueryInterfaceSafe ((Object), \ 00664 iSCF::SCF->GetInterfaceID (#Interface), VERSION_##Interface)) 00665 00673 extern void scfInitialize (iConfigFile *iConfig = 0); 00674 00681 static inline bool scfCompatibleVersion (int iVersion, int iItfVersion) 00682 { 00683 return ((iVersion & 0xff000000) == (iItfVersion & 0xff000000)) 00684 && ((iVersion & 0x00ffffff) <= (iItfVersion & 0x00ffffff)); 00685 } 00686 00687 #ifdef CS_DEBUG 00688 struct iObjectRegistry; 00689 #endif 00690 00691 SCF_VERSION (iSCF, 0, 0, 1); 00692 00699 struct iSCF : public iBase 00700 { 00702 static iSCF *SCF; 00703 00704 #ifdef CS_DEBUG 00705 // This is EXTREMELY dirty but I see no other solution for now. 00706 // For debugging reasons I must have a global (global over the application 00707 // and all plugins)pointer to the object registry. I have no other 00708 // global object to tag this pointer on that except for iSCF. 00709 // This pointer is only here in debug mode though. That ensures that it 00710 // cannot be misused in real code. 00711 // If you know another solution for this problem? This global pointer 00712 // will be used by csDebuggingGraph in csutil. 00713 iObjectRegistry* object_reg; 00714 #endif 00715 00720 virtual void RegisterConfigClassList (iConfigFile *Config) = 0; 00721 00728 virtual bool ClassRegistered (const char *iClassID) = 0; 00729 00745 virtual void *CreateInstance (const char *iClassID, 00746 const char *iInterface, int iVersion) = 0; 00747 00753 virtual const char *GetClassDescription (const char *iClassID) = 0; 00754 00760 virtual const char *GetClassDependencies (const char *iClassID) = 0; 00761 00768 virtual void UnloadUnusedModules () = 0; 00769 00777 virtual bool RegisterClass (const char *iClassID, 00778 const char *iLibraryName, const char *Dependencies = NULL) = 0; 00779 00786 virtual bool RegisterStaticClass (scfClassInfo *iClassInfo) = 0; 00787 00796 virtual bool RegisterClassList (scfClassInfo *iClassInfo) = 0; 00797 00804 virtual bool UnregisterClass (const char *iClassID) = 0; 00805 00811 virtual scfInterfaceID GetInterfaceID (const char *iInterface) = 0; 00812 00819 virtual void Finish () = 0; 00820 00831 virtual iStrVector* QueryClassList (char const* pattern) = 0; 00832 }; 00833 00834 #endif // __CSSCF_H__ Generated for Crystal Space by doxygen 1.2.5 written by Dimitri van Heesch, ©1997-2000 |