⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 dynobj.cpp

📁 The library provides supports for run-time loaded plugin classes in C++
💻 CPP
📖 第 1 页 / 共 3 页
字号:
// 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 + -