📄 dynobj.cpp
字号:
// Copyright (c) 2007, Arne Steinarson// Licensing for DynObj project - see DynObj-license.txt in this folder#include <string.h>#include <stdio.h> // ## Debug#include <assert.h> // ## Debug#define DO_IMPLEMENTING #define DO_IMPLEMENT_DYNOBJ#define DO_IMPLEMENT_DOBASEI #define DO_IMPLEMENT_DOBASE #define DO_IMPLEMENT_DORTINT#define DO_IMPLEMENT_DODYNSHARED#include "utils/ExpArr.hpp"#include "DynObj.h"#include "DynObjMethods.h"#include "DoError.h"#include "DoBaseI.h" #include "DoBase.hpp" #include "DortInt.h" #include "vt_test.h"#if DO_USE_DYNSHARED==1 #include "DoDynShared.hpp"#endif #if DO_ENABLE_VTABLE_DISPATCH==1 #include "pi/SpinLock.h"#endif #if DO_USE_RUNTIME==1 #include "DORT.h" static DoRunTimeI *g_dort; #ifdef DO_MAIN DoRunTimeI *MainGetDort(); // DoRunTime calls here to set the instance void doSetRunTime( DoRunTimeI* pdort ){ g_dort = pdort; } #endif DoRunTimeI &doGetRunTime(){ #ifdef DO_MAIN if( !g_dort ) MainGetDort(); // This will trigger instantiation if not done yet #endif return *g_dort; } /* #if defined(DO_MODULE) // If in a module using DoRunTime, declare the global var DoRunTimeI *g_dort; DoRunTimeI &ModuleGetDort(){ return *g_dort; } #endif */#endif//// Globals //// Symbols exported to library loader//int g_do_platform = DO_PLATFORM;#ifdef DO_IMPLEMENTED_TYPES static const char *g_do_implements = DO_IMPLEMENTED_TYPES;#else static const char *g_do_implements;#endif // For building implemented type variablestatic const char *g_do_allocated_str;// To extract a reference to the ponterstruct ExpArrPDoTypes : public ExpArrP<DynObjType*> { DynObjType**& GetBasePointerRef( ) {_CFE_; return this->ta; }};// Used during global construction, use pointers and Get function// These could be more efficient data types //ExpArrP<DynObjType*> *g_do_types;static ExpArrPDoTypes *g_do_types;static ExpArrP<DynObjType*> *g_do_types_unres; // Put types with unresolved base class herestatic ExpArrPOwn<MIBSideType*> *g_do_mibst; // They might be the same in various libs, but that doesn't really matter//static int g_do_side_type_id = DO_MBI_SIDE_1ST_ID; static bool g_do_init;static int g_do_base_init; // Signal not to notify DynObj lib on object destructionExpArrP<DynObjType*> &doGetTypes(){_CFE_; if( !g_do_types ) g_do_types = new ExpArrPDoTypes; //ExpArrP<DynObjType*>; return *g_do_types;}ExpArrP<DynObjType*> &doGetTypesUnres(){_CFE_; if( !g_do_types_unres ) g_do_types_unres = new ExpArrP<DynObjType*>; return *g_do_types_unres;}ExpArrP<MIBSideType*> &DoGetMibst(){_CFE_; if( !g_do_mibst ) g_do_mibst = new ExpArrPOwn<MIBSideType*>; return *g_do_mibst;}void DynObjType_BpDummy(){_CFE_; int z=3;}// For working with VTables#if DO_ENABLE_VTABLE_CORR==1 #include "DoVTableInfo.hpp" static ExpArrPOwn<VTableInfo*> g_do_vtbls;#endif // DO_ENABLE_VTABLE_CORR// The DoModuleC interface (DoRunTimeI making calls to us)class DoModule : public DoModuleC { virtual DynObjType* docall FindType( void** vtbl ){_CFE_; return doGetTypes().Find(vtbl); } virtual DynObjType* docall FindType( const char *type ){_CFE_; return doGetTypes().Find(type); } virtual DynObjType* docall FindType( int type_id ){_CFE_; return doGetTypes().Find(type_id); }};static DoModule g_do_mod;// For closing down moduleextern "C" SYM_EXPORT void doExit( );// Module constructionclass DynObj_ModConstr {public: DynObj_ModConstr() { // No need to do anything, vt_test.cpp runs the class/VFunc tests automatically } ~DynObj_ModConstr(){ // Unregister all types/VTables with DoRunTime // For main program, no point in doing this, since we might interfere // with shutdown, and all types are being deleted anyway. DO_LOG("DynObj.cpp module unload"); doExit( ); delete [] g_do_allocated_str; delete g_do_types; delete g_do_types_unres; delete g_do_mibst; g_do_types = NULL; g_do_types_unres = NULL; g_do_mibst = NULL; }} g_do_mod_constr;// Make type available to library users in g_do_implementsbool doAddImplemented( const char *type, int type_id ){_CFE_;#if defined(DO_DEBUG) //DO_TRACE1("doAddImplemented %s entry\n", type?type:"??" );#endif if( !type || (type_id>0 && type_id<VOBJ_TYPE_ID) ){ DO_LOG_ERR(DOERR_INCORRECT_TYPE_ID,"doAddImplemented: No type give or too low type_id"); return false; } char buf[32]; int sl = (int)((g_do_implements?strlen(g_do_implements):0) + strlen(type) + 16); char *pc = new char[sl]; if( !pc ){ DO_LOG_ERR(DOERR_NO_MEMORY,"doAddImplemented: No mem (new failed)"); return false; } // Build new type string if( g_do_implements && *g_do_implements ){ strcpy(pc,g_do_implements); strcat(pc,","); } else *pc = 0; strcat(pc,type); strcat(pc,","); sprintf(buf,"0x%08X",type_id); strcat(pc,buf); delete [] g_do_allocated_str; g_do_allocated_str = pc; g_do_implements = pc; #if defined(DO_DEBUG) DO_TRACE1( "g_do_implements: %s \n", g_do_implements ); /* int mod = -1; #ifdef DO_MODULE mod = 1; #elif DO_MAIN mod=0; #endif printf("g_do_implements: %x &:%x module: %d \n", g_do_implements, &g_do_implements, mod ); */#endif return true;}const char *doGetImplemented( ){_CFE_; return g_do_implements;}//// Implementation, VObj//DynObjType* VObj::GetType( ) const { return ::doGetType(this);}/*void* VObj::GetObj( const char *type, DynObjType *pdt ) {_CFE_; return ::doGetObj(this,pdt,type);} VObj* VObj::GetVObj( const char *type, DynObjType *pdt ) {_CFE_; DynObjType *pdt_found; void* pobj = ::doGetObj(this,pdt,type,doCastCross,&pdt_found); if( !pobj ) return NULL; if( pobj==this ) return this; return pdt_found->IsA(VOBJ_TYPE_ID) ? reinterpret_cast<VObj*>(pobj) : NULL;} DynI* VObj::GetDynI( const char *type, DynObjType *pdt ) {_CFE_; DynObjType *pdt_found; void* pobj = ::doGetObj(this,pdt,type,doCastCross,&pdt_found); if( !pobj ) return NULL; return pdt_found->IsA(DYNI_TYPE_ID) ? reinterpret_cast<DynI*>(pobj) : NULL;} void* VObj::GetObj( int type_id, DynObjType *pdt ) {_CFE_; return ::doGetObj(this,pdt,type_id,doCastCross);}VObj* VObj::GetVObj( int type_id, DynObjType *pdt ) {_CFE_; DynObjType *pdt_found; void* pobj = ::doGetObj(this,pdt,type_id,doCastCross,&pdt_found); if( !pobj ) return NULL; if( pobj==this ) return this; return pdt_found->IsA(VOBJ_TYPE_ID) ? reinterpret_cast<VObj*>(pobj) : NULL;}DynI* VObj::GetDynI( int type_id, DynObjType *pdt ) {_CFE_; DynObjType *pdt_found; void* pobj = ::doGetObj(this,pdt,type_id,doCastCross,&pdt_found); if( !pobj ) return NULL; return pdt_found->IsA(DYNI_TYPE_ID) ? reinterpret_cast<DynI*>(pobj) : NULL;}*/bool VObj::IsA( const char *type, DynObjType *pdt ) const { if( !this || !type ) return false; if( !pdt && !(pdt = ::doGetType(this)) ) return false; //return pdt->IsA(type); DynObjType *dot_isa = doFindType(type); return dot_isa ? pdt->IsA(dot_isa->_type_id) : false;}bool VObj::IsA( int type_id, DynObjType *pdt ) const { if( !this || !type_id ) return false; if( !pdt && !(pdt = ::doGetType(this)) ) return false; return pdt->IsA(type_id);}/*bool VObj::CanBeA( const char *type, DynObjType *pdt ){_CFE_; if( !this || !type ) return false; if( !pdt && !(pdt = ::doGetType(this)) ) return false; DynObjType *dot_isa = doFindType(type); return dot_isa ? pdt->CanBeA(dot_isa->_type_id) : false;}*/bool VObj::CanBeA( int type_id, DynObjType *pdt ) const { if( !this || !type_id ) return false; if( !pdt && !(pdt=::doGetType(this)) ) return false; return pdt->CanBeA(type_id);}const char* VObj::GetError( int *perr_code ) const {#if DO_USE_RUNTIME==1 if( &DORT ) return DORT.GetObjectError( this, perr_code );#endif return NULL;}void VObj::ClearError( ){_CFE_;#if DO_USE_RUNTIME==1 if( &DORT ) bool rv = DORT.ClearObjectError( this );#endif }bool VObj::SetError( const char *err_str, int err_code ) const { bool rv = false;#if DO_USE_RUNTIME==1 if( &DORT ) rv = DORT.SetObjectError( this, err_str, err_code );#else DO_LOG_ERR( err_code, err_str );#endif return rv;}//// Implementation, DynI//// Can return a pointer to any object it knows it contains.// This uses the type information stored in DynObjType and keeps track of// inherited bases and side base classes. // Note: When overriding this function in DynI derived classes, always call // this base version if you cannot resolve the type in the customized function.void* doGetObj( DynI *pdi, const char *type, doCastAlgo algo, DynObjType **pdt_found, bool inernal_from_dyni );void* DynI::doGetObj( const char *type ) {_CFE_; return ::doGetObj(this,type,doCastCross,NULL,true);}const char* DynI::doGetError( int *perr_code ) const { return VObj::GetError( perr_code );}void DynI::doClearError( ){_CFE_; return VObj::ClearError( );}//void DynI::doSetError( const char *err_str, int err_code ){// return VObj::SetError( err_str, err_code );//}//// Implementation, DynObj//DynObj::~DynObj(){_CFE_;#if DO_USE_RUNTIME==1 // Tracking is a client feature, not a library one, so we shouldn't // disable it from here. if( &DORT && g_do_base_init>=0 ){ DynObjType *dot_rt = DORT.doGetType(); DortInternalI *pdorti = (DortInternalI*)::doGetObj( &DORT, DORTINTERNALI_TYPE_ID, dot_rt ); if( pdorti ) // Let DORT do object tracking pdorti->OnObjectDestroy( this ); }#endif}#if DO_ENABLE_VTABLE_CORR==1// A class to hold the method for retrieving type info for side classes // as in C[A]:C in A : public B, public C// C[A] is a distinct type, and we need it to return its own type (not// its base type)class DynObjSideType : public DynObj {public: virtual DynObjType* docall doGetType( const DynI **pself ) const { if( !this ) return NULL; void **vtbl = *(void***)this; //return doGetTypes().Find(vtbl); VTableInfo *vtp = g_do_vtbls.Find(vtbl); return vtp ? vtp->pdt : NULL; } virtual void docall doDestroy() {_CFE_; // Do nothing at all. }};#endif // DO_ENABLE_VTABLE_CORRDynObjType *doFindType( const char *type ){_CFE_; return doGetTypes().Find(type);}DynObjType *doFindType( int type_id ){_CFE_; return doGetTypes().Find(type_id);}// This is an early init, while global construction still happensvoid doEarlyInit( DoRunTimeI *pdort=NULL ){ if( !g_do_init ){#if DO_USE_RUNTIME==1 #ifdef DO_MODULE if( pdort && !&DORT ){ g_dort = pdort; DO_ASSERT_MSG( &DORT, "doEarlyInit - No DoRunTimeI available" ); } #endif if( &DORT ){ g_do_init = true; DORT.RegisterModule( &g_do_mod ); #ifdef DO_MAIN // Not stricty necessary DORT.RegisterType( *(void***)&g_do_mod, g_do_mod.doGetType(NULL) ); #endif }#else g_do_init = true;#endif }}// Constructors for DynObjLibImpl #include "pi/compiler.h"DynObjType **g_do_dummy_types;DynObjLibImpl::DynObjLibImpl(const char *cs, const char *impl, int dt, int pf) : _sh(sizeof(DynObjLibImpl),0,0), _call_str(cs), _implements(impl), _do_traits(dt), _platform(pf), _lib_name(DO_LIB_NAME), _lib_descr(DO_LIB_DESCR), _lib_author(DO_LIB_AUTHOR), _lib_major_ver(DO_LIB_MAJOR_VERSION), _lib_minor_ver(DO_LIB_MINOR_VERSION), _compiler(PI_COMPILER), _comp_major_ver(PI_COMPILER_VERSION), _comp_minor_ver(PI_COMPILER_VERSION_MINOR), _types(g_do_dummy_types), _module(0), _lib_flags( 0 // Setup flags for the library#if DO_USE_RUNTIME==1 |DOLI_USES_RUNTIME // Set this flag by default. It is really a client decision. // DynObj destructor by default calls back to DORT if DORT is available. |DOLI_OBJECT_TRACKING#endif ), _dynobj_major_ver(DYNOBJ_MAJOR_VERSION), _dynobj_minor_ver(DYNOBJ_MINOR_VERSION) {_CFE_; }//DynObjLibImpl::DynObjLibImpl() : _sh(sizeof(DynObjLibImpl),0,0), _call_str(0), _implements(0), _do_traits(0), _platform(0) { } DynObjLibImpl g_do_lib_impl(DO_CALLSTR,NULL,0,DO_PLATFORM_FLAGS);// Called from outside when library has been loaded (usually by DynObjLib)extern "C" SYM_EXPORT DynObjLibImpl* doBaseInit( DoRunTimeI *pdort ){ // Make sure internally setup (will usually be) if(pdort) doEarlyInit( pdort ); g_do_base_init = -1;#if DO_USE_RUNTIME==1 // While instantiating temp objects, stop further objects from being created DortInternalI *pdorti = (DortInternalI*)::doGetObj( pdort, DORTINTERNALI_TYPE_ID, doCastCross ); if( pdorti ) pdorti->TempDisableCreate( true );#endif // Go over types and see if we can run doConstruct on them // (over plain registration it has the advantage of registering sub objects) for( EapIter<DynObjType*> it(doGetTypes()); it(); it++ ){ if( !it()->_vtbl && it()->_cdofn ){ printf("Creating and registering %s\n", it()->_type ); // No VTable yet, but we have an instantiate function int vtbl_size = -1; void *pv = it()->_cdofn(&vtbl_size); if( !pv ) { DO_LOG_ERR1(DOERR_FAILED_REGISTER_INSTANTIATE, "Failed instantiate during doBaseInit registration: ", it()->_type ); } else{ // Now we have both a VTable and VTable size //it()->_vtbl = *(void***)pv; - doConstruct does this! it()->_vtbl_size = vtbl_size; doConstruct( (VObj*)pv, it(), !it()->IsSideBase() ); // Destroy temp object it()->_dcdofn(pv); } }#if DO_USE_RUNTIME==1 else if( it()->_vtbl && pdort ) // Have VTable so it should be registered pdort->RegisterType(it()->_vtbl,it());#endif
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -