📄 dotype.h
字号:
// Copyright (c) 2007, Arne Steinarson// Licensing for DynObj project - see DynObj-license.txt in this folder#ifndef DOTYPE_H#define DOTYPE_H#include <stddef.h> // NULL defined// Three main classes (in base to derived order)class VObj;class DynI;class DynObj;class DoModuleC;#include "utils/StructHeader.h"struct MIBSideType;#define DOT_SIDE_TYPE SH_FLAG1/** @ingroup Utils * Different cast algorithms. * An object with several base classes can be searched in different ways. * This makes a difference if the current object is a sub-object of a larger * compound object. * The default algorithm is DoCastCross, which allows for going moving to a compound * type once. */enum doCastAlgo { /** Look along main base line and among side bases. * This cannot go from a side base to the main base*/ doCastLocal = 1, /** Allow one jump to the compound object. * This can jump from a side base to a main base once.*/ doCastCross = 2, /** Cast from outermost object. * Go to the outermost object and do exhaustive cast * This will find a subobject wherever it is hidden * in a nested side base. */ doCastFull = 3, };// Create instances during setuptypedef void* (*InstVObjFn)(int *pvts);// Destroy instances during setuptypedef void (*DeInstVObjFn)(void *pv);// A structure to identify the type of the DynObj (or another type not derived// from DynObj).// All objects of the same class returns the same DynObjType - a static instance.//// Both _type_id and _type identify the type of the object (they say the// same thing). It's purpose is to more strongly identify the implemented// interface (if someone else has implemented your 'vehicle' class and you// accidently open that library, then chances are they have not given their// 'vehicle' class the type_id==0x51b7de00).//// When an interface needs to be expanded, instead of changing to a new type// one ticks the _version member one step forward and derives a new interface// class from the old one./** @ingroup Utils * Internal representation of a type. * This keeps all data representing the internals of a registered DynObjType. * All data fields are generated by the source compiler, allowing for using * the correct object offsets in the hos application. */struct DynObjType{public: // The "flags_version" argument has flags in 16 upper bits and version in 16 lower bits DynObjType( const char *type, int type_id, int flags_version, int size, const void *_this=NULL, const void *_base_ptr=NULL ); void Ctor( const char *type, int type_id, int flags_version, int size, const void *_this, const void *_base_ptr ); ~DynObjType( ); StructHeader _sh; // Verifies that this is a DynObjType data struct const char* _type; // Name of the class/interface. Base class names are not present here. int _type_id; // same as ID in CreateFn int _size; // sizeof(DynObj) - size of an object of this type short _version; // Version of the implemented type short _offset; // Offset - for multiple and virtual inheritence short _vtbl_size; // Number of entries in VTable or -1 if not known short _flags; // See below //protected: DynObjType* _base; // Base type (primary) void** _vtbl; // VTable for this type or NULL if unknown or an object with no virtual funcs MIBSideType* _base_side; // With multiple inheritence, first side base type DoModuleC* _module; // The module that creates this type, allows for tracking back an object // on destruction. DynObjType* _idc_prv; // Previous DynObjType with same ID DynObjType* _idc_nxt; // Next DynObjType with same ID InstVObjFn _cdofn; // Used if instantiating objects during setup DeInstVObjFn _dcdofn; // Used if instantiating objects during setup bool operator == (const char *type) const; bool operator == (void **vtbl) const { return vtbl && vtbl==_vtbl; } bool operator == (int type_id) const { return type_id==_type_id; } bool IsA( int type_id ) const; bool CanBeA( int type_id ) const; bool IsSideBase() const { return _sh.Flags()&DOT_SIDE_TYPE ? true : false; } DynObjType *GetOuterMost() const; DynObjType *GetTypeAtOffset( int off ) const; // This is for hashing. inline void** GetKey( ){ return (void**)_vtbl; } protected: // Exhaustive GetObj (tries all sub types recursively) void *GetObjExh( void *pself, const char *type, DynObjType **found_type=NULL ); void *GetObjExh( void *pself, int type_id, DynObjType **found_type=NULL ); // Only tries main line and side line (direct bases and direct side bases) void *GetObj( void *pself, const char *type, DynObjType **found_type=NULL ); void *GetObj( void *pself, int type_id, DynObjType **found_type=NULL ); bool CanBeAInternal( int type_id ) const; friend void* doGetObj( void *obj, const char *type, DynObjType *self_type, doCastAlgo algo, DynObjType **pdt_found ); friend void* doGetObj( void *obj, int type_id, DynObjType *self_type, doCastAlgo algo, DynObjType **pdt_found ); friend void* doGetObj( DynI *pdi, const char *type, doCastAlgo algo, DynObjType **pdt_found, bool internal_from_dyni );};#ifdef DO_IMPLEMENTING// For flags field#define DOT_DID_INIT 1 // Type initialized & registered (after calling doConstruct & DORT.RegisterType)#define DOT_DESTROY_SOFT 2 // For DynObj type, in a sub object, set DoDostroy to harmless method #define DOT_USER_TYPE 4 // A user type (not internal, abstract or side base). Can be instantiated.#define DOT_NO_VTABLE_CORR 8 // Do not correct VTable for this type#define DOT_STATIC_TYPE 16 // Instances of this type are static#if DO_ENABLE_VTABLE_CORR==1 #include "DoVTableInfo.hpp" #endif// Helper function to get instance of DynI/Vobj derived template<class T>void* VObjTempInstance( int *pvts ){#if DO_ENABLE_VTABLE_CORR==1 if( pvts ) *pvts = GetVTableSizeOf<T,void>();#endif return new T;}template<class T>void VObjTempInstanceDelete( void *pv ){ ::delete (T*)pv;}// Helper to get temp instance of DynObj derivedclass DynI;template<class T>void* DynObjTempInstance( int *pvts ){#if DO_ENABLE_VTABLE_CORR==1 if( pvts ) *pvts = GetVTableSizeOf<T,DynI*>();#endif return new T((DynI*)NULL);}// This is for the case when we instantiate a class to register it in the // global constructor. The condition for doing this is that it has a // constructor that takes no arguments (VObj/DynI derived) or that it has // a DynObj constructor (one argument of type DynI*).// This saves us from the trouple of calling doConstruct manually at a // later point.//#include <stdio.h>template<class MainCl, class BaseCl=void, bool is_dynobj=false>class DynObjTypeI2R;// Specialization for DynObj derivedtemplate<class MainCl, class BaseCl>class DynObjTypeI2R<MainCl,BaseCl,true> : public DynObjType {public: DynObjTypeI2R( const char *type, int type_id, int flags_version ) : DynObjType( type, type_id, flags_version, sizeof(MainCl) ) { _cdofn = (InstVObjFn)DynObjTempInstance<MainCl>; _dcdofn = VObjTempInstanceDelete<MainCl>; /* MainCl mc; // Local instance here _offset = short((char*)static_cast<BaseCl*>(&mc) - (char*)&mc);#if DO_ENABLE_VTABLE_CORR==1 _vtbl_size = GetVTableSizeOf<MainCl>( );#endif _vtbl = *(void***)&mc; */ }};// Specialization for VObj & DynI derivedtemplate<class MainCl, class BaseCl>class DynObjTypeI2R<MainCl,BaseCl,false> : public DynObjType {public: DynObjTypeI2R( const char *type, int type_id, int flags_version ) : DynObjType( type, type_id, flags_version, sizeof(MainCl) ) { _cdofn = VObjTempInstance<MainCl>; _dcdofn = VObjTempInstanceDelete<MainCl>; }};// For multiple inheritence, this represents a side base type// It sets the _sh flag DOT_SIDE_TYPE in the constructor. // NOTE: Side base types are separate types in themselves (if it has virtual funcs)// For A : public B, public C { } we have the distinct types A, B, C, C[A]// C[A] is generated automatically struct MIBSideType : public DynObjType { MIBSideType( DynObjType *compound, short offset, const char *type, int type_id, int ver, int size, const void *_this, int vtbl_size ); DynObjType* _compound; // The main type (where this type is always a side base)};// To get offset to side bases in a type safe way template <class Base, class SideBase>int sidebase_offset( const Base *pb=NULL ){ // It seems static_cast wants non-zero values to do its job of // converting on known class type offsets, even though it doesn't // use RTTI info. If NULL input, use arbitrary address if( !pb ) pb = reinterpret_cast<const Base*>(&pb); const SideBase *pcb = static_cast<const SideBase*>(pb); return (int)(reinterpret_cast<const char*>(pcb) - reinterpret_cast<const char*>(pb));}// Used when declaring side base classesclass SideBaseDecl {public: SideBaseDecl( const char *main_cl, const char *side_base_cl, int size, int off, const void *_this, int vtbl_size, void **vtbl_o ) { Ctor(main_cl, side_base_cl, size, off, _this, vtbl_size, vtbl_o); } void Ctor( const char *main_cl, const char *side_base_cl, int size, int off, const void *_this, int vtbl_size, void **vtbl_o );};// Macro to add side base classes in a type safe way #define DO_ADD_SIDE_BASE(MainCl,SideBaseCl)\ SideBaseDecl g_sbd_##MainCl##SideBaseCl( #MainCl,#SideBaseCl,sizeof(SideBaseCl),sidebase_offset<MainCl,SideBaseCl>(),NULL,GetVTableSizeOf<SideBaseCl>(),GetVTableOf<SideBaseCl>() )// Macro to add side base classes in a type safe way inside doGetType (using this pointer)// Used inside doGetType. Does not detect size of VTables.// Forces doGetType on Side base class #define DO_ADD_SIDE_BASE_THIS(MainCl,SideBaseCl) { \ this->SideBaseCl::doGetType( const DynI **pself=0 ); \ static SideBaseDecl sbdt(#MainCl,#SideBaseCl,sizeof(SideBaseCl),sidebase_offset<MainCl,SideBaseCl>(this),this,-1,NULL); \ }// Macro to add side base classes in a type safe way inside doGetType (using this pointer)// Used inside doGetType. Detects size of VTables.// Forces doGetType on Side base class #define DO_ADD_SIDE_BASE_THIS_VTABLE_CORR(MainCl,SideBaseCl) { \ this->SideBaseCl::doGetType( const DynI **pself=0 ); \ static SideBaseDecl sbdt(#MainCl,#SideBaseCl,sizeof(SideBaseCl),sidebase_offset<MainCl,SideBaseCl>(this),this,GetVTableSizeOf<SideBaseCl>(),GetVTableOf<SideBaseCl>()); \ }#endif // DO_IMPLEMENTING #endif // DOTYPE_H
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -