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

📄 dynobj.cpp

📁 The library provides supports for run-time loaded plugin classes in C++
💻 CPP
📖 第 1 页 / 共 3 页
字号:
        // Check if side base that derives from DynI (and would require VTable correction)#if DO_ENABLE_VTABLE_CORR!=1 && !defined(DI_GET_TYPE_GLOBAL)        if( it()->IsSideBase() ){            if( it()->IsA(DYNI_TYPE_ID) ){                DO_LOG1( "doBaseInit: The side-base type %s is derived from DynI. Casts FROM this base to other\n"                         "bases when using DynI::doGetObj / DynI::doGetType are unsafe. Use DI_GET_TYPE\n"                         "in that case (or enable VTable correction).", it()->_type );            }        }#endif // DO_ENABLE_VTABLE_CORR    }    	// Check if we have unresolved types	for( EapIter<DynObjType*> it(doGetTypesUnres()); it(); it++ )		DO_LOG1( "doBaseInit: Unresolved - %s", it()->_type );        // Make sure types are NULL terminated now    if( !doGetTypes().Size() || doGetTypes().Top() )        doGetTypes().Push(NULL);            // Set up DynObjLibImpl fields    if( !g_do_lib_impl._module ){        g_do_lib_impl._implements = g_do_implements;        g_do_lib_impl._do_traits = doGetDoTraits();        g_do_lib_impl._types = g_do_types->GetBasePointerRef( );         g_do_lib_impl._module = &g_do_mod;    }        g_do_base_init = 1;#if DO_USE_RUNTIME==1    if( pdorti )        pdorti->TempDisableCreate( false );#endif        return &g_do_lib_impl;}// Called on unloading a library, to remove module and types from DoRunTimeextern "C" SYM_EXPORT void doExit( ){#if defined(DO_MODULE) && DO_USE_RUNTIME==1	if( &DORT ){		for( EapIter<DynObjType*> it(doGetTypes()); it(); it++ ){			if( it()->_vtbl )				DORT.UnRegisterType(it()->_vtbl);		}		DORT.UnRegisterModule( &g_do_mod );		g_dort = NULL;#if DO_ENABLE_VTABLE_CORR==1		for( EapIter<VTableInfo*> it(g_do_vtbls); it(); it++ )			DORT.UnRegisterType(it()->vtbl_o);#endif 	}#endif}//#include "pi/compiler.h"DynObjType::DynObjType( const char *type, int type_id, int flag_ver, int size, 							   const void *this_ptr, const void *base_ptr ) : 		_sh(sizeof(DynObjType),0,0), _type(NULL), _type_id(type_id), _version(0), _size(size),		_base(NULL), _vtbl(NULL), _base_side(NULL), _vtbl_size(-1), _flags(0),         _module(NULL), _cdofn(NULL), _dcdofn(NULL),         _idc_prv(0), _idc_nxt(0) {_CFE_;		//void **_ebp;	//GET_FRAME_PTR(_ebp);	//void *caller = _ebp ? _ebp[-1] : NULL;	//printf("::DynObjType - _ebp:%p    caller:%p    doExit:%p    &doExit:%p\n", _ebp, caller, doExit, &doExit );		// GCC ctor bug, force ordinary function	Ctor( type, type_id, flag_ver, size, this_ptr, base_ptr );}void DynObjType::Ctor( const char *type, int type_id, int flag_ver, int size, 							   const void *this_ptr, const void *base_ptr ) {_CFE_;	_flags = short(flag_ver>>16);	_version = short(flag_ver&0xFFFF);	if( !type ){		DO_LOG_ERR(DOERR_EMPTY_TYPE_STRING,"::DynObjType: Empty type string received\n"); 		return; 	}        if( type_id&(~TYPE_ID_MASK) )        DO_LOG2( "::DynObjType: type id (%08X) for %s uses bits outside default ID mask", type_id, type );		_module = &g_do_mod;		// Did we get a pointer to an object? 	// This is only useful for user-types and side bases (which set vtable themselves)	if( _flags&DOT_USER_TYPE && this_ptr ){		_vtbl = *(void***)this_ptr;#if DO_USE_RUNTIME==1		// This is best time to register the type		if( &DORT ) DORT.RegisterType( _vtbl, this );#endif	}		// For virtual inheritance, the base pointer is different to the this_ptr	// _offset ends up negative below for virtual inheritance	_offset = this_ptr && base_ptr ? (short)(((const char*)this_ptr)-((const char*)base_ptr)) : 0;		const char *pc = strchr(type,':');	if( !pc ){		// Simple case, no base class 		char *str = new char[strlen(type)+1];		if( !str ) return;	// ## Set error		strcpy(str,type);		_type = str;	}	else{		int bcl = (int)strlen(pc+1);		const char *br_pos = strchr(type,']');	// For side bases		if( strchr(br_pos?br_pos+2:pc+1,':') ){			DO_LOG_ERR1(DOERR_EXPECTED_ONLY_ONE_BASE,"::DynObjType: More than one direct base class given: %s\n",type); // An error 			return;		}		if( !strncmp(pc+1,type,bcl) && type[bcl]==':' ){			DO_LOG_ERR1(DOERR_TYPE_USES_SELF_AS_BASE,"::DynObjType: Type referring to itself as base class found: %s\n",type); // An error 			return;		}		// Look for base type in our module		DynObjType *pdt = doGetTypes().Find(pc+1);		if( pdt ){			if( pdt==this ){				DO_LOG_ERR1(DOERR_TYPE_USES_SELF_AS_BASE,"::DynObjType: Type referring to itself as base class found: %s\n",type); // An error 				return;			}			_base = pdt;		}		else{			// Resolve base type later			doGetTypesUnres().Push(this);			//DO_TRACE1( "Unresolved type: %s\n", type );			pc = pc+strlen(pc);		}		char *str = new char[pc+1-type];		if( !str ) return;	// ## Set error		strncpy(str,type,pc-type);		str[pc-type] = 0;		_type = str;	}	// Before pushing, check that we don't have this class already	// (also, protect from instances created on the stack and repeatedly	// registered/destroyed).	DynObjType *pdt;	for( int ix=doGetTypes().Size()-1; ix>=0; ix-- ){		pdt = doGetTypes()[ix];		if( pdt->_sh.m_magic!=SH_MAGIC ){			DO_LOG1("Invalid DynObjType structure at %p\n",pdt);			doGetTypes().RemoveIndexUnordered(ix);		}		if( pdt->_type_id==_type_id ){			if( SIDEBASE_TYPE_ID!=_type_id ||				!strcmp(pdt->_type,_type) ){				DynObjType_BpDummy();				DO_LOG_ERR2(DOERR_TYPE_ALREADY_EXISTS,"::DynObjType: Constructing already existing DynObjType structure %s (%p)\n",pdt->_type,pdt);				return;			}		}	}	// Register it	doGetTypes().Push(this);	//DO_TRACE1( "Registering type: %s\n", _type );		// Does this new type resolve base for some other types?	for( EapIter<DynObjType*> it(doGetTypesUnres()); it(); it++ ){		const char *pc = strchr(it()->_type,':');		if( pc ){		   int tl = (int)strlen(pc+1);			if( !strncmp(_type,pc+1,tl) && (!_type[tl] || _type[tl]==':') ){				//DO_TRACE1( "Resolving type: %s\n", it()->_type );				*(char*)pc = 0;	// Know base class, remove ':'				it()->_base = this;				doGetTypesUnres().RemoveIndexUnordered(it.Index());				it--;			}		}	}}MIBSideType::MIBSideType( DynObjType *compound, short offset, const char *type, int type_id, int ver, int size, 								  const void *_this, int vtbl_size )	 : DynObjType( type, type_id, ver, size, _this?((const char*)_this)+offset:NULL ), 		_compound(compound) {_CFE_;     _sh.SetFlags(_sh.Flags()|DOT_SIDE_TYPE); // So that it's possible to tell we're a derived object 	_offset = offset;     // Override 0 from DynObjType ctor	_vtbl_size = vtbl_size;	if( _this ){		// Since we're a side base, we know that this VTable is ours		_vtbl = *(void***)_this;#if DO_USE_RUNTIME==1		if( &DORT ) DORT.RegisterType( _vtbl, this );#endif	}}DynObjType::~DynObjType(){_CFE_; 	_sh.m_magic = 0;	// Erase the magic marker	delete [] _type; }bool DynObjType::operator==(const char *type) const {	if( !type ) return false;	// Need to match also when unresolved 	int tl = (int)strlen(type);	if( strncmp(_type,type,tl) ) return false;	return !_type[tl] || _type[tl]==':'; }bool DynObjType::IsA( int type_id ) const {	return _type_id==type_id ? true : (_base?_base->IsA(type_id):false);}bool DynObjType::CanBeAInternal( int type_id ) const {	if( _type_id==type_id ) return true;	if( _base && _base->CanBeAInternal(type_id) ) return true;	if( IsSideBase() ) return false;	for( DynObjType *psb=_base_side; psb; psb=psb->_base_side )		if( psb->CanBeAInternal(type_id) ) return true;	return false;}// This searches for the requested type from the outermost type// (global, exhaustive)bool DynObjType::CanBeA( int type_id ) const {    if( !this ) return false;    const DynObjType *pdt = GetOuterMost();    return pdt->CanBeAInternal( type_id );}DynObjType* DynObjType::GetOuterMost() const {    if( !this ) return NULL;    const DynObjType *pdt = this;    while( pdt->IsSideBase() ){        pdt = ((MIBSideType*)pdt)->_compound;        DO_ASSERT_MSG( pdt, "GetOuterMost - No outermost type found" );    }    return (DynObjType*)pdt;}DynObjType* DynObjType::GetTypeAtOffset( int off ) const {    if( !this || off<0 ) return NULL;	// We could do it for <0 also, but no point    if( !off ) return (DynObjType*)this;        // Walk side bases until we know where to find type    const DynObjType *pdt = this;    while(  pdt->_base_side && off>=pdt->_base_side->_offset )    	pdt = pdt->_base_side;    if( !pdt ) return NULL;    off -= pdt->_offset;        /*    // This could happen for virtual base classes (?)    while( off>0 && pdt->_base ) {    	off -= pdt->_offset;    	pdt = pdt->_base;    }    */        return !off ? (DynObjType*)pdt : NULL;}// Recursive casting on type stringvoid* DynObjType::GetObj( void *pobj, const char *type, DynObjType **found_type ){_CFE_;		// No checking of args, this function can only be called from inside DynObj.cpp	DynObjType *pdt;		// Self? 	if( !strcmp(_type,type) ){ 		if( found_type ) *found_type=this;		return pobj;	}	 	// Try all main bases 	int off = IsSideBase() ? 0 : _offset; 	for( pdt=_base; pdt; pdt=pdt->_base ){		if( !strcmp(pdt->_type,type) )			return ((char*)pobj) - off;		off += pdt->_offset;	}	// Try each side type (start at its base)	if( !IsSideBase() ){		DynObjType *pst;		for( pst=_base_side; pst; pst=pst->_base_side ){			off = pst->_offset; // Side base class offset			for( pdt=pst->_base; pdt; pdt=pdt->_base ){				if( !strcmp(pdt->_type,type) ){					if( found_type ) *found_type=pdt;					return ((char*)pobj) + off;				}				off -= pdt->_offset;	// These are virtual base class offsets			}		}	}		// Done	return NULL;}// Recursive casting on type stringvoid* DynObjType::GetObjExh( void *pobj, const char *type, DynObjType **found_type ){_CFE_;		// No checking of args, this function can only be called from inside DynObj.cpp	// We try the direct bases from left to right	if( !strcmp(_base->_type,type) ){		if( found_type ) *found_type=this;		return ((char*)pobj) - (IsSideBase() ? 0 : _offset);	}	// Try each side type 	if( !IsSideBase() ){		for( DynObjType *pdt=_base_side; pdt; pdt=pdt->_base_side )			if( !strcmp(pdt->_type,type) ){				if( found_type ) *found_type=pdt;				return ((char*)pobj) + pdt->_offset;			}	}		// recursively do the same iteration	void *pco;	if( _base->_base && (pco=_base->GetObjExh(((char*)pobj)-(IsSideBase() ? 0 : _offset),type,found_type)) )		return pco;	// Try each side type 	if( !IsSideBase() ){		DynObjType *pst;		for( pst=_base_side; pst; pst=pst->_base_side )			if( pst->_base && (pco=pst->GetObjExh(((char*)pobj)+pst->_offset,type,found_type)) )				return pco;	}		// Exhausted	return NULL;}// Recursive casting on type stringvoid* DynObjType::GetObj( void *pobj, int type_id, DynObjType **found_type ){_CFE_;		// No checking of args, this function can only be called from inside DynObj.cpp	DynObjType *pdt;		// Self? 	if( _type_id==type_id ){		if( found_type ) *found_type=this;		return pobj;	}	 	// Try all main bases 	int off = IsSideBase() ? 0 : _offset; 	for( pdt=_base; pdt; pdt=pdt->_base ){		if( pdt->_type_id==type_id ){			if( found_type ) *found_type=pdt;			return ((char*)pobj) - off;		}		off += pdt->_offset;	}	// Try each side type (start at its base)	if( !IsSideBase() ){		DynObjType *pst;		for( pst=_base_side; pst; pst=pst->_base_side ){			off = pst->_offset; // Side base class offset			for( pdt=pst->_base; pdt; pdt=pdt->_base ){				if( pdt->_type_id==type_id ){					if( found_type ) *found_type=pdt;					return ((char*)pobj) + off;				}				off -= pdt->_offset;	// These are virtual base class offsets			}		}	}	// Done	return NULL;}// Recursive casting on type idvoid* DynObjType::GetObjExh( void *pobj, int type_id, DynObjType **found_type ){_CFE_;		// No checking of args, this function can only be called from inside DynObj.cpp	// We try the direct bases from left to right	if( _base->_type_id==type_id ){		if( found_type ) *found_type=this;		return ((char*)pobj) - (IsSideBase() ? 0 : _offset);	}	// Side bases themselves, per definition have no side bases. 	// If ordinary base, Try each side type 	if( !IsSideBase() ){		for( DynObjType* pdt=_base_side; pdt; pdt=pdt->_base_side )			if( pdt->_type_id==type_id ){				if( found_type ) *found_type=pdt;				return ((char*)pobj) + pdt->_offset;			}	}		// recursively do the same iteration	void *pco;	if( _base->_base && (pco=_base->GetObjExh(((char*)pobj)-(IsSideBase() ? 0 : _offset),type_id,found_type)) )		return pco;	// Try each side type recursively	if( !IsSideBase() ){		DynObjType *pst;		for( pst=_base_side; pst; pst=pst->_base_side )			if( pst->_base && (pco=pst->GetObjExh(((char*)pobj)+pst->_offset,type_id,found_type)) )				return pco;	}		// Exhausted	return NULL;}	// Instantiated to add a side base class to the typevoid SideBaseDecl::Ctor( const char *main_cl, const char *side_base_cl, int size, int off, const void *_this, int vtbl_size, void **vtbl_o ){_CFE_;	//BPDummy();	if( !main_cl || !side_base_cl ) return;	DynObjType *ptype =  doGetTypes().Find( main_cl );	if( !ptype ){		DO_LOG_ERR1(DOERR_SIDEBASE_NOT_FOUND,"SideBaseDecl: Main class not found: %s\n",main_cl);		return;	}	if( off<=0 || off>32767){		DO_LOG_ERR2(DOERR_SIDEBASE_OFFSET_OUT_OF_RANGE,"SideBaseDecl: [%s] Invalid offset: %d\n",side_base_cl,off);		return;	}		// Check that there is space in main object 	if( off+size>ptype->_size ){		DO_LOG_ERR(DOERR_SIDEBASE_NO_SPACE_IN_MAIN,"SideBaseDecl: Not enough space in containing object.");		return;	}		// Side types are their own types, derived from side_base_cl given above. 	// (unless a type with no virtual functions)	// make new name and allocate new structure for it. 	// ## We could make a template to test for a virtual class	int ptl = (int)strlen(ptype->_type);	int sbl = (int)strlen(side_base_cl);	char *str = new char[sbl+2+ptl+1+sbl+1];	if( !str ){ DO_LOG_ERR(DOERR_NO_MEMORY,"SideBaseDecl: Mem alloc failed."); return; }	strcpy(str,side_base_cl);	strcat(str,"[");	strcat(str,ptype->_type);	// Don't want to include unresolved base of our base in name	char *pc = strchr(str+sbl,':');	if( pc ) *pc=0;	strcat(str,"]:");	strcat(str,side_base_cl);		// This will auto register new type 	// Side types don't need unique IDs since they're not addressed from outside	MIBSideType *pst = new MIBSideType(ptype,off,str,SIDEBASE_TYPE_ID,1,size,_this,vtbl_size);	//MIBSideType *pst = new MIBSideType(ptype,off,str,g_do_side_type_id,1,size,_this,vtbl_size);	//g_do_side_type_id -= STEP_TYPE_ID;		if( pst->_base ){		// The VTable given as an argument is the one of the base of the side class		if( vtbl_o && !pst->_base->_vtbl ) pst->_base->_vtbl = vtbl_o;		// For a side type, VTable size is identical to parent VTable size		if( vtbl_size<=0 && pst->_base->_vtbl_size>=0 )			pst->_vtbl_size = pst->_base->_vtbl_size;	}	delete [] str;	if( !pst ) { DO_LOG_ERR(DOERR_NO_MEMORY,"SideBaseDecl: Mem alloc failed."); return; } 	DoGetMibst().Push(pst);		// Add last among side bases (order does not matter, since offset is absolute)	while( ptype->_base_side )		ptype = ptype->_base_side;	ptype->_base_side = pst;}// Main init function (manually called after global construction is done)bool doInit( ){_CFE_;#if defined(DO_MAIN)    #if DO_USE_RUNTIME==1    // Make sure DoRunTime VTable is known	doConstruct(&DORT,DORT.doGetType(NULL),true);    #endif    // This will setup any registered types    doBaseInit( NULL );#endif		return !doGetTypesUnres().Size();}//// Resolve type for arbitrary object with VTable// DynObjType* doGetType( const void* pobj ){_CFE_;	if( !pobj ){		DO_LOG( "doGetType called on NULL instance" );		return NULL;	}	void **vtbl = *(void***)pobj;	DynObjType *pdt;#if DO_USE_RUNTIME==1	DoRunTimeI *pdort = &DORT;

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -