📄 dynobj.h
字号:
// Copyright (c) 2007, Arne Steinarson// Licensing for DynObj project - see DynObj-license.txt in this folder#ifndef DYNOBJ_H#define DYNOBJ_H// These are directives to preprocessing tool that auto-generates some of the required code // %%DYNOBJ options generate(implement) // Defines and config options are in here#include "DoSetup.h"// Type system#include "DoType.h"// Error logging#include "DoError.h"// Preprocessor symbols controlling how DynObj.h and related files://// DO_IMPLEMENTING - from a C++ source file that implements a DynObj// DO_MAIN - from the main program (that loads other DynObjs and has the DoRunTimeI instance)// DO_MODULE - Set when compiling a library/loadable module (that does not own DoRunTimeI)// DO_IMPLEMENTED_TYPES - Define before compiling DynObj.cpp to set to a list of implemented// type names /type IDs. This how types are made 'public'. Example//// "string,0xB314DA4,Car:VehicleI,0xBA618F23"//// Another method is to use doAddImplemented or global instances of// class DoImplDecl (later this file).// #ifdef DO_MODULE #ifdef DO_MAIN #error Both DO_MODULE and DO_MAIN are defined (only one should be) #endif#elif defined(DO_MAIN) // Fine, do nothing#else // Proceed until the defs are needed, give warning there#endif// Doxygen stuff/** @defgroup DynI DynI derived classes *//** @defgroup VObj VObj interfaces and base classes (not derived from DynI) *//** @defgroup ImplClass Other classes *//** @defgroup DynI derived classes *//** @defgroup Utils Global functions, enums *//** @defgroup Library Library interface and setup *//** @defgroup DynTemplate Central DynI templates *//** @defgroup DynDefs DynObj defines */// Object IDs: // They can be generated automatically from the "pdoh" tool (Parse DynObj Header). // Layout of ID:// Bit 0..7 - Set to 0 for now// Bit 8..30 - Custom type ID// Bit 31 - Set for user-type without VTable // Custom IDs start at BASE_CUSTOM_TYPE_ID (0x10000)// The next one is 0x10100, 0x10200, and so on#define TYPE_ID_MASK 0xFFFFF000 // Bits 12..31// Base type IDs: - They should probably be positive#define SIDEBASE_TYPE_ID 0xFFFFF000 // All side bas classes have this type ID (cannot be addressed individually from outside)#define OUTERMOST_TYPE_ID 0xFFFFD000 // When casting to the outermost object (the container object) (string OUTERMOST)#define COMPOUND_TYPE_ID 0xFFFFE000 // When casting to a compound object (the container object) (string COMPOUND)#define INVALID_TYPE_ID 0xFFFFF000 // Just same as unknown for now#define UNKNOWN_TYPE_ID 0 // Hmmm...#define VOBJ_TYPE_ID 0x00001000#define DYNI_TYPE_ID 0x00002000#define DYNOBJ_TYPE_ID 0x00003000#define DYNSHAREDI_TYPE_ID 0x00004000#define DYNDATA_TYPE_ID 0x00006000#define RTDYNSHARED_TYPE_ID 0x00008000#define DORUNTIMEI_TYPE_ID 0x00010000#define DORTINTERNALI_TYPE_ID 0x00011000#define DOMODULEC_TYPE_ID 0x00012000#define DORT_TYPE_ID DORUNTIMEI_TYPE_ID#define DYNSTR_TYPE_ID 0x00013000#define DYNARRCHAR_TYPE_ID 0x00020000#define DYNARRSHORT_TYPE_ID 0x00021000#define DYNARRINT_TYPE_ID 0x00022000#define DYNARRINT64_TYPE_ID 0x00023000#define DYNARRPTR_TYPE_ID 0x00024000#define DYNARRPTR_VOBJ_TYPE_ID 0x00025000#define DYNARRPTR_DYNI_TYPE_ID 0x00026000#define NOTIFIERI_TYPE_ID 0x00030000#define NOTIFIABLEI_TYPE_ID 0x00031000#define NOTDATAI_TYPE_ID 0x00032000#define BASE_CUSTOM_TYPE_ID 0x00100000#define STEP_TYPE_ID 0x00001000 // How much to increment for each type#if DO_NO_TYPEINFO!=1/** Translate C++ type to type string and type ID. * This provides a way to get type ID and type name for any known (registered) class. * Implement for each class that is exposed. See DO_DECL_TYPE_INFO further down.*/template<class T>struct doTypeInfo { static int Id( ){ return UNKNOWN_TYPE_ID; } static const char* Name( ){ return NULL; } //enum { TypeId=INVALID_TYPE_ID };};/// @cond internal// Peels off pointertemplate<class T>struct doTypeInfo<T*> {public: static int Id( ){ return doTypeInfo<T>::Id(); } static const char* Name( ){ return doTypeInfo<T>::Name(); } //enum { TypeId=doTypeInfo<T>::TypeId };};// Peels off reftemplate<class T>struct doTypeInfo<T&> {public: static int Id( ){ return doTypeInfo<T>::Id(); } static const char* Name( ){ return doTypeInfo<T>::Name(); } //enum { TypeId=doTypeInfo<T>::TypeId };};// Peels off consttemplate<class T>struct doTypeInfo<const T> {public: static int Id( ){ return doTypeInfo<T>::Id(); } static const char* Name( ){ return doTypeInfo<T>::Name(); } //enum { TypeId=doTypeInfo<T>::TypeId };};#endif //DO_NO_TYPEINFO/// @endcond internal //squRegisterMemberFn( sd.v, sd.newClass.GetObjectHandle(), sqbVObj_GetObj, _T("GetObj") );#if DO_FAT_VOBJ==1// Need this proto belowvoid* doGetObj( void* pobj, const char *type, DynObjType *self_type, doCastAlgo algo=doCastCross, DynObjType **found_type=NULL );void* doGetObj( void* pobj, int type_id, DynObjType *self_type, doCastAlgo algo=doCastCross, DynObjType **found_type=NULL );void* doGetObj( DynI* pdi, const char *type, doCastAlgo algo=doCastCross, DynObjType **found_type=NULL );void* doGetObj( DynI* pdi, int type_id, doCastAlgo algo=doCastCross, DynObjType **found_type=NULL );DynObjType* doGetType( const void* pobj );DynObjType* doGetType( const DynI* pdi );#endif/** @ingroup VObj * This is the 'stipulated' base class for objects with virtual functions. * * In this class the virtual functions (number of them, signatures) are not known. * It only promises that it has a VTable, and we can do type lookups from that. * VObjs can be used when we have C++ classes that don't derive from DynI. * Objects of type VObj are not created, but one can get pointers to them through * casts/queries (doGetVObj). */// %%DYNOBJ class(vobj) <- Tag for header file preprocessing class VObj {public: // With fat VObj we get a lot of non-virtual convenience functions for the base class. // NOTE: Requires static linking (to DynObj.cpp) #if DO_FAT_VOBJ==1 /** @name Non-virtuals * Functions included with DO_FAT_VOBJ define */ //@{ /** Returns type structure for this object. * Does a global lookup using object VPTR. */ DynObjType* GetType( ) const; /** Test if object is of a certain type ID * IsA returns true if the requested type can be returned without * adjusting the 'this' pointer (must be main base class). */ bool IsA( int type_id ) const { return IsA(type_id,NULL); } /** Test if object 'can be' of a certain type ID * CanBeA returns true if the requested type is available as any base * class of the object (main base or side base). */ bool CanBeA( int type_id ) const { return CanBeA(type_id,NULL); } /** Same as IsA but using type string */ // Lookup is not done on custom addon types. bool IsA( const char *type ) const { return IsA(type,NULL); } //bool CanBeA( const char *type ) { return CanBeA(type,NULL); } /** Raw cast, lookup internal type by type ID. */ void* GetObj( int type_id, doCastAlgo algo=doCastCross ) { return ::doGetObj(this,type_id,NULL,algo); } /** Raw cast, lookup internal type by type string. */ void* GetObj( const char *type, doCastAlgo algo=doCastCross ) { return ::doGetObj(this,type,NULL,algo); } /** Returns current error string for object or NULL if no error * @param perr_code a location to store the error code, default is NULL * @return The error string or NULL if no error. */ const char* GetError( int* perr_code=NULL ) const; /** This will clear the error state for the object if set */ void ClearError( ); /** Set the internal error state for the object */ bool SetError( const char *err_str, int err_code=-1 ) const; bool IsA( int type_id, DynObjType *ptype ) const; bool CanBeA( int type_id, DynObjType *ptype ) const; bool IsA( const char *type, DynObjType *ptype ) const; //bool CanBeA( const char *type, DynObjType *ptype ); const char *GetTypeName( ) const { DynObjType *pdt = ::doGetType(this); return pdt ? pdt->_type : NULL; } /** Check if object exists and has no errors * Check if 'this' is non-NULL and that object has no error */ bool IsOk( ) const { return this && !GetError(); } //@} #endif // DO_FAT_VOBJ};/** @ingroup DynI * The effective root class of the DynObj library. * * This is the base type representing objects, interfaces and sub-objects * created by the DynObj package. In itself it is an interface. It knows its * own type and can be queried for custom owned objects. * * For compatibility with MSVC++, the member function calling convention 'docall' * must be put between the return type and the function name: * virtual int ->docall<- MyFunc( int i ); */// %%DYNOBJ class(dyni) <- Tag for header file preprocessing class DynI : public VObj {public: /** @name Virtuals * Interface members */ //@{ /** Returns type of this object. * Each type that wants to make itself known should override this method. * DynI knows its own type so we get the type without any lookup. * It is faster and works without registration. * * @param pself allows fetching the actual 'this' used inside doGetType * (from a side base, this will be different to the 'this' of the caller). * @return A DynObjType pointer */ virtual DynObjType* docall doGetType( const DynI **pself=NULL ) const; /** 'Smart cast' (parallel to QueryInterface) used to retrieve another * interface or sub-object that the object supports. * The default implementation of doGetObj traverses the registered main and side * base classes for the object and returns any match found there. This is the same * search as done when querying for types using type IDs. * * A derived version can also check the argument type string and return a pointer * to an owned object that is not a base class (custom types). The rule is that the * returned object should have the same life span as this one, they are part of the * same compound object. * * When overriding this method, and not returning a custom object directly, one should * call the immediate base class version. Then, after traversing the inheritance chain, * the call will end up in the base version DynI::doGetObj. There, the call will be * made to check for any registered base class types. * * For versions with type safety, use do_cast or do_cast_str. * * @return A pointer to the found interface/internal object. */ virtual void* docall doGetObj( const char *type ); // Works for all objects, even data structures /** Returns current error string for object or NULL if no error. * Object errors are used to handle errors that are not detected through return * codes, i.e. exceptions. The default implementation uses DoRunTime for this. Errors * are unique to the object but stored outside of it. No memory is used for this until * an error is set. * @param perr_code a location to store the error code, default is NULL * @return The error string or NULL if no error. */ virtual const char* docall doGetError( int* perr_code=NULL ) const; /** This will clear the error state for the object if set */ virtual void docall docall doClearError( ); //@} #if DO_FAT_VOBJ==1 /** @name Inlines * Inline convenience functions */ //@{ // Convenience functions for accesing DynI type info // Non virtual, inline, generated on both sides, therefore OK DynObjType *GetType() const { return ::doGetType(this); } bool IsOk( ) const { return this && !doGetError(); } const char *GetTypeName( ) const { DynObjType *pdt=DI_GET_TYPE(this); return pdt ? pdt->_type : NULL; } int GetTypeId( ) const { DynObjType *pdt=DI_GET_TYPE(this); return pdt ? pdt->_type_id : -1; } int GetTypeVersion( ) const { DynObjType *pdt=DI_GET_TYPE(this); return pdt ? pdt->_version : -1; } int GetObjectSize( ) const { DynObjType *pdt=DI_GET_TYPE(this); return pdt ? pdt->_size : -1; } bool IsA( int type_id ) const { return VObj::IsA( type_id, DI_GET_TYPE(this) ); } bool CanBeA( int type_id ) const { return VObj::CanBeA( type_id, DI_GET_TYPE(this) ); } bool IsA( const char *type ) const { return VObj::IsA( type, DI_GET_TYPE(this) ); } //bool CanBeA( const char *type ) { return VObj::CanBeA( type, DI_GET_TYPE(this) ); } /** Raw cast, lookup internal type by type ID. */ void* GetObj( int type_id, doCastAlgo algo=doCastCross ) { return ::doGetObj(this,type_id,algo); } /** Raw cast, lookup internal type by type string. */ void* GetObj( const char *type, doCastAlgo algo=doCastCross ) { return ::doGetObj(this,type,algo); } //@} /** @name Others * Other member functions */ //@{ // This is only intended for user of a DynObj to be able to use ordinary // delete on the object and route the call back to the creator. // NOTE: When an application defines its own operator new and/or redefines // the new/delete keywords (to support memory tracking), this may not work. // To be safe its best to call doDestroy directly from the app. #if DO_ENABLE_OPERATOR_DELETE==1 void operator delete( void *pv ){ SetError( "DynObj::operator delete on a DynI", DOERR_DELETE_ON_DYNI ); } #endif // DO_ENABLE_OPERATOR_DELETE //@} #endif // DO_FAT_VOBJ};// Used as a NULL object #define DynINull (*(DynI*)(0))/** @ingroup DynI * This class represents objects that can be created and destroyed. It is the * type of new objects created (from type names/type IDs). To destroy a DynObj, * the function doDestroy is used. */// %%DYNOBJ class(dyni) <- Tag for header file preprocessing class DynObj : public DynI {public: /** @name Virtuals * Interface members */ //@{ // All DynI derived types overrides this virtual DynObjType* docall doGetType( const DynI **pself=0 ) const; /** doDestroy is invoked by the owner to delete it. * An implementation should both call its own most derived C++ destructor and * the object memory. A typical implementation would be: * MyClass::doDestroy(){ ::delete this; } */ virtual void docall doDestroy( ) { };
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -