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

📄 dynobj.cpp

📁 The library provides supports for run-time loaded plugin classes in C++
💻 CPP
📖 第 1 页 / 共 3 页
字号:
	// This should be fastest, DoRunTime has a hash table for lookup	if( pdort && (pdt=pdort->GetTypeOf(vtbl)) )		return pdt;#endif	// Look among all our types 	pdt = doGetTypes().Find(vtbl);	if( pdt ) return pdt;#if DO_ENABLE_VTABLE_CORR==1	// Look among SideBase types with modified VTables	VTableInfo *vtp = g_do_vtbls.Find(vtbl);	if( vtp ) return vtp->pdt;#endif	return pdt;}DynObjType* doGetType( const DynI* pdi ){_CFE_;	if( !pdi ){		DO_LOG( "doGetType called on NULL instance" );		return NULL;	}	const DynI *pself = NULL;	DynObjType *pdt = pdi->doGetType( &pself );	if( !pdt ) return NULL;	if( pself==pdi ) return pdt;	if( !pself ){		DO_LOG1("Warning: ::doGetType - The type %s does not fill in pself in diGetType", pdt->_type );		return NULL;	}		// Case where we received pointer to the compound type	DynObjType *pdt_sub = pdt->GetTypeAtOffset( int(((char*)pdi) - ((char*)pself)) );	if( pdt_sub ) return pdt_sub;		DO_LOG_ERR2( DOERR_UNKNOWN_TYPE, "::doGetType - Retrieved compound type but failed finding sub-type: (instance:%p, type:%s)", pdi, pdt->_type );	return NULL;}//// This is the casting based on DynObjType structure//// NOTE: We can also support a cast to an outermost main object// by repeatedly moving from side base and doing a new type lookup//// Helper function for common string casevoid* doGetObjCommon( void* pobj, DynObjType *pdt, const char *type, DynObjType **pdt_found ){_CFE_;	// Request for itself?	if( type && !strcmp(type,pdt->_type) ){		if( pdt_found ) *pdt_found=pdt;		return pobj;	}		// Request for compound object?	if( !type || !strcmp(type,"COMPOUND") ){		if( pdt->IsSideBase() ){			if( pdt_found ) *pdt_found=pdt;			// Adjust object pointer			return ((char*)pobj) - pdt->_offset;		}        else return NULL;	}		// Request for compound object?	if( !strcmp(type,"OUTERMOST") ){		while( pdt && pdt->IsSideBase() ){            pobj = ((char*)pobj) - pdt->_offset;            pdt = ((MIBSideType*)pdt)->_compound;		}        if( pdt_found ) *pdt_found=pdt;        return pobj;	}		return NULL;}void* doGetObj( void* pobj, const char *type, DynObjType *pdt, doCastAlgo algo, DynObjType **pdt_found ){_CFE_;	if( !pobj ) return NULL;		// No type yet?	if( !pdt ){		pdt = ::doGetType(pobj);		if( !pdt ) return NULL;	}		// Sort out common simple cases	void* pco = doGetObjCommon( pobj, pdt, type, pdt_found );	if( pco ) return pco;		// If caller is a DynI we should route to the specialized function	if( pdt->IsA(DYNI_TYPE_ID) )		return doGetObj( (DynI*)pobj, type, algo, pdt_found, false );		// If we have base class, do a full GetObj at this level 	if( pdt->_base )		pco = pdt->GetObjExh(pobj,type,pdt_found);	if( pco ) return pco;		// If we're a side base in a compund object, do casting from point 	// of view of compound object.	if( !pdt->IsSideBase() || algo==doCastLocal )		return NULL;	    // Try cross cast at next compound level    while( true ){        pobj = ((char*)pobj)-pdt->_offset;        pdt = ((MIBSideType*)pdt)->_compound;        if( !pdt ) break;        pco = pdt->GetObjExh(pobj,type,pdt_found);        if( pco )            return pco;        if( algo<doCastFull || !pdt->IsSideBase() )            break;    }        return NULL;}void* doGetObj( void* pobj, int type_id, DynObjType *pdt, doCastAlgo algo, DynObjType **pdt_found ){_CFE_;	if( !pobj ) return NULL;	if( !pdt && !(pdt = ::doGetType(pobj)) )        return NULL;	    void* pco;    switch( type_id ){            case COMPOUND_TYPE_ID:            // If we are the compound object, return self            if( pdt->IsSideBase() ){                if( pdt_found ) *pdt_found=pdt;                // Adjust object pointer                return ((char*)pobj) - pdt->_offset;            }            else return NULL;                    case OUTERMOST_TYPE_ID:            while( pdt && pdt->IsSideBase() ){                pobj = ((char*)pobj) - pdt->_offset;                pdt = ((MIBSideType*)pdt)->_compound;            }            if( pdt_found ) *pdt_found = pdt;            return pobj;        default:            // Request for itself?            if( type_id==pdt->_type_id ){                if( pdt_found ) *pdt_found=pdt;                return pobj;            }                    // If we have base class, do a full GetObj at this level            if( pdt->_base ){	            pco = pdt->GetObjExh(pobj,type_id,pdt_found);	            if( pco ) return pco;            }                        // If we're a side base in a compund object, do casting from point             // of view of compound object.            if( !pdt->IsSideBase() )                return NULL;                        break;    }		    // Try cross cast at next compound level    while( true ){        pobj = ((char*)pobj)-pdt->_offset;        pdt = ((MIBSideType*)pdt)->_compound;        if( !pdt ) break;        pco = pdt->GetObjExh(pobj,type_id,pdt_found);        if( pco )            return pco;        if( algo<doCastFull || !pdt->IsSideBase() )            return NULL;    }        return NULL;}// Declare as non member function//typedef void* docall (*doGetObjFn)(DynI* _this, const char *type);typedef void* (*doGetObjFn)(DynI* _this, const char *type);//// Version for ::doGetObj with a string for DynI which gives priority // to DynI::doGetObj, allowing custom types to be accessed recursively.// // This is also entry point for call from from DynI::doGetObj void* doGetObj( DynI *pdi, const char *type, doCastAlgo algo, DynObjType **pdt_found, bool internal_from_dyni ){_CFE_;	if( !pdi ) return NULL; 			DynObjType *pdt = DI_GET_TYPE(pdi); 	if( !pdt ){		DO_LOG_ERR1(DOERR_UNKNOWN_TYPE, "::doGetObj - failed looking up type", pdi );		return NULL;	}	#if DO_ENABLE_VTABLE_DISPATCH==1	// Lock so only one thread can enter    static SpinLock st_sl_getobj;	SpinLocker sl(st_sl_getobj);	if( !sl.IsOk() ) return NULL;#endif    		// Last caller context	static DynI *pdi_last;	DynI *pdi_prev = pdi_last;	pdi_last = pdi;		void *pobj = NULL;		if( !internal_from_dyni ){		// First entry into function		// Call derived DynI::doGetObj for custom casts. That will call back to us		pobj = pdi->doGetObj(type);	}		else{#if DO_ENABLE_VTABLE_DISPATCH==1 		// Recursive entry (always from inside DynI::doGetObj)		// The derived class is responsible for calling its base		// class version of doGetObj until DynI::doGetObj calls here		// So we only have to check side bases now		if( !pdt->IsSideBase() ){			// for all bases			for( DynObjType* pst=pdt->_base_side; pst && !pobj; pst=pst->_base_side ){				// Only if Dyni or more derived				if( pst->IsA(DYNI_TYPE_ID) && pst->_vtbl ){					doGetObjFn fn = (doGetObjFn)pst->_vtbl[VTableIndex(DYNI_DOGETOBJ)];					if( fn ){						// This invokes the virtual function for the side base class						// Add base offset						DynI *pdi_rec = (DynI*)(((char*)pdi)+pst->_offset);						pdi_last = pdi_rec;						pobj = fn(pdi_rec,type);					}				}			}		}#endif // DO_ENABLE_VTABLE_DISPATCH        }	// Restore caller context	pdi_last = pdi_prev;		if( !pobj ){	// No result yet?		if( !pdi_prev ){ // If this is outermost call			// Resolve in same way as ::doGetObj						// Sort out common simple cases (self, compound)			pobj = doGetObjCommon( pdi, pdt, type, pdt_found );			if( !pobj && type ){				// Use DynObjType cast				if( pdt->_base ) pobj = pdt->GetObjExh(pdi,type,pdt_found);				// With 1st entry, we're safe to expand the call to compound type				if( !pobj && pdt->IsSideBase() ){                                    // Try cross cast at compound levels                    while( true ){                        pdi = (DynI*)(((char*)pdi)-pdt->_offset);                        pdt = ((MIBSideType*)pdt)->_compound;                        if( !pdt ) break;                        pobj = pdt->GetObjExh(pdi,type,pdt_found);                        if( pobj )                            break;                        if( algo<doCastFull || !pdt->IsSideBase() )                            break;                    }				}			}		}	}		return pobj;}void* doGetObj( DynI* pdi, const char *type, doCastAlgo algo, DynObjType **found_type ) {_CFE_;	return pdi ? ::doGetObj( pdi, type, ::doGetType(pdi), algo, found_type ) : NULL;}void* doGetObj( DynI* pdi, int type_id, doCastAlgo algo, DynObjType **found_type ) {_CFE_;	return pdi ? ::doGetObj( pdi, type_id, ::doGetType(pdi), algo, found_type ) : NULL;}//// Logging/Error reporting functions//void DO_PUTS(const char *str){_CFE_;	if( !str || !*str ) return;#if DO_USE_RUNTIME==1	if( &DORT ){		DORT.GetTextIo()->puts(str);		return;	}#endif		puts(str);}// Appends new linevoid DO_LOG( const char *str ){_CFE_;	if( !str ) str="";	DO_PUTS( str );	int sl = (int)strlen(str);	if( sl==0 || str[sl-1]!='\n' )		DO_PUTS( "\n" );}void DO_LOG_ERR(int code, const char *str ){_CFE_;	if( !str ) str="";#if DO_USE_RUNTIME==1	if(&DORT){		DORT.SetLastError(code,str);		return;	}#endif	char buf[32];	int sl = (int)strlen(str);	sprintf( buf, "(Error: 0x08%X) - ", code );	fprintf(stderr, "(Error: 0x08%X) - %s%c", code, str, sl && str[sl-1]=='\n' ? ' ' : '\n' );}// This will do one or two things:// 1 - For a DynI derived object, it will set soft VTable for each side //     base object (restore doGetType and doGetObj)// 2 - For all objects it will register all contained //     types with DoRunTime (including side types with their own VTables)// Note: If not using VTable correction nor DoRunTime, this method does no workbool doConstruct( const VObj *pobj, DynObjType *pdt, bool is_outer ){_CFE_;	if( !pobj ) return false;		// This method goes from compound objects to sub-objects. 	if( !pdt && !(pdt=::doGetType(pobj)) ){		DO_LOG_ERR1(DOERR_CANT_FIND_TYPE,"doConstruct: Cannot find type (NULL in doGetType (%P))\n",pobj);		return false;	}	// Non VObj:s, stop here (nothing to do)	if( !pdt->IsA(VOBJ_TYPE_ID) ) return false;		// If we've done this type before, stop here    bool do_set_init = true;	if( is_outer ){#if DO_ENABLE_VTABLE_CORR==0        // If not VTable correction, nothing to do after registering 1st instance.		if( pdt->_flags&DOT_DID_INIT )			return true;#endif            #if DO_USE_RUNTIME==1		// Only want to set flag if DoRunTime is initialized by now		if( !&DORT ) do_set_init=false;#endif	}	// If VTable for this type not set, do so now, but not recursively on main branch	// Also OK to do for virtual base class (offset!=0) and side bases	if( ((!pdt->_flags&DOT_DID_INIT) || !pdt->_vtbl) &&         pdt->_base && (is_outer || pdt->IsSideBase() || pdt->_offset) ){		pdt->_vtbl = *(void***)pobj;#if DO_USE_RUNTIME==1		// The right time to register, since we run this recursively, on all 		// base types and derived types.		if( &DORT ) DORT.RegisterType( pdt->_vtbl, pdt );	}	// This catches the case when type already have a VTable set, but we encounter it	// with yet another VTable (happens with nested multi base class)	else if( pdt->IsSideBase() && pdt->_vtbl!=*(void***)pobj )		if( &DORT ) DORT.RegisterType( *(void***)pobj, pdt );#else	}#endif    if( do_set_init )        pdt->_flags |= DOT_DID_INIT;	// Iterate over main base classes - invoke doConstruct recursively	// But do not do it for VObj itself (nothing to setup for it)	int off = pdt->IsSideBase() ? 0 : -pdt->_offset;	if( pdt->_base && pdt->_base->_base && !doConstruct( (VObj*)((char*)pobj)+off,pdt->_base,false) )		return false;    // Everything below relates to setting up side-base VTables, so return early if possible    if( pdt->IsSideBase() || !pdt->_base_side )         return true;	bool is_di = pdt->IsA(DYNOBJ_TYPE_ID);	bool is_do = is_di && pdt->IsA(DYNI_TYPE_ID);		// Iterate over each of the side bases	for( MIBSideType *pst = pdt->_base_side; pst; pst=pst->_base_side ){		// For a side type, VTable size is identical to parent VTable size		if( pst->_vtbl_size<=0 && pst->_base->_vtbl_size>=0 )			pst->_vtbl_size = pst->_base->_vtbl_size;				void *po = ((char*)pobj)+pst->_offset;		bool should_install = is_di && pst->IsA(DYNI_TYPE_ID);		bool did_install = false;		if( pst->_base->_flags&DOT_NO_VTABLE_CORR )			should_install = false;				// If known VTable size#if DO_ENABLE_VTABLE_CORR==1		if( should_install && pst->_vtbl_size>0 ) {			void **vtbl = *(void***)po;			// If actual VTable don't match type			VTableInfo *vtp = g_do_vtbls.Find(vtbl);			if( !vtp ){				vtp = new VTableInfo(vtbl,pst->_base->_vtbl,pst->_vtbl_size);				if( !vtp ) return false;				if( !vtp->AllocSoftVTbl() ){ delete vtp; DO_LOG_ERR(DOERR_NO_MEMORY,"doConstruct: AllocSoftVTbl failed."); return false; }				vtp->pdt = pst;	// Bind back to type				g_do_vtbls.Push(vtp);								// Restore entries in soft vtable				/*if( pst->IsA(DynI) )*/{					static 	DynObjSideType dost;	                    // Restoring doGetType and doGetObj to local methods					vtp->vtbl_r[VTableIndex(DYNI_DOGETTYPE)] = (*(void***)&dost)[VTableIndex(DYNI_DOGETTYPE)]; // doGetType for side objects					vtp->vtbl_r[VTableIndex(DYNI_DOGETOBJ)] = vtp->vtbl_o[VTableIndex(DYNI_DOGETOBJ)];		  // doGetObj					if( pst->_flags&DOT_DESTROY_SOFT && is_do )                        // Set doDestroy to 'harmless' method						vtp->vtbl_r[VTableIndex(DYNOBJ_DODESTROY)] = (*(void***)&dost)[VTableIndex(DYNOBJ_DODESTROY)]; // doDestroy for side objects					DO_TRACE1("doConstruct: Restoring VTable DynI methods for %s", pst->_type ); 				}				// # We could have mechanism in type to specify which methods to restore			}			// Already set? (should not be)			if( vtbl!=vtp->vtbl_r ){				// Install soft VTable				*(void***)po = vtp->vtbl_r;				pst->_vtbl = vtp->vtbl_r;			}			did_install = true;		}		if( should_install && !did_install )			DO_LOG1("doConstruct (%s): A sidebase (derived from DynI), but could not restore original methods.\nCasts FROM this type will not work.", pst->_type ); #endif				if( !doConstruct((VObj*)po,pst,false) )			return false;	}		return true;}void doReleaseDestroy( DynObj *pdo ){_CFE_;    if( !pdo ) return;    DynSharedI *pds = (DynSharedI*)::doGetObj(pdo,DYNSHAREDI_TYPE_ID,DI_GET_TYPE(pdo));    if( pds )         pds->doRelease();    else        pdo->doDestroy( );}#include "pi/compiler.h"bool doIsStatic( const VObj *pvo, DynObjType *pdt ){_CFE_;	if( !pvo ) return false;	if( !pdt ) pdt = doGetType(pvo);		// It is enough that it derives from a type that is static	DynObjType *pdt1 = pdt->GetOuterMost();	for( pdt1=pdt; pdt1; pdt1=pdt1->_base )		if( pdt1->_flags&DOT_STATIC_TYPE )			break;	if( !pdt1 ) return false;	#if DO_USE_RUNTIME==1	if( !&DORT ) return false;	// If object type is in the same module as DORT, then accept	if( DORT.doGetType(NULL)->_module==pdt->_module ) 		return true;		// Get callers address (return address is in callers module)	void **_ebp;	GET_FRAME_PTR(_ebp);	void *caller = _ebp ? _ebp[-1] : NULL;	// If callers module is same as module for type, then accept	// # Need DoRunTimeI support	//if( DORT.GetModuleFor(caller)==pdt->_module ) 	//	return true;	#else	// Accept if the type of the object is from the same module as this one	if( pdt->_module = &g_do_mod ) 		return true;#endif		return false;}bool doIsStatic( const DynI *pdi ){_CFE_; 	return pdi ? doIsStatic((VObj*)pdi,DI_GET_TYPE(pdi)) : false; }

⌨️ 快捷键说明

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