Teigha SDK Developer 运行时类型识别 #2

文章目录

Kernel SDK Developer’s Guide

Run-Time Type Identification

Registering and Unregistering Classes in a Program

注册一个类是一个重要的过程,它为一个类创建类描述实例并将其添加到类字典中——生成类标识并在运行时获得可访问的类信息。取消注册类是删除类信息并使类标识在运行时不可访问的过程。
每个类必须有自己的注册方法—rxInit()—和自己的取消注册方法—rxUninit()ODRX_DEFINE_INIT_MEMBERS宏为指定的类创建rxInit()rxUninit()方法的默认实现。其他宏使用这个宏定义rxInit()rxUninit()方法。
在默认实现中,rxInit()方法使用newOdRxClass()全局函数创建OdDxfClassImpl类的实例,该类创建OdRxClass纯方法的标准RTTI实现。OdRxClass类是OdRxObject类的继承者,继承了numRefsaddRefrelease虚方法,newOdRxClass()函数还使用OdRxObjectImpl类来包装OdDxfClassImpl类,以实现引用计数功能的标准实现。然后newOdRxClass()函数调用OdDxfClassImpl类的init()方法来初始化有关正在注册的类的信息,并在类的字典中添加关于该类的新项。newOdRxClass()函数返回描述实例的类的原始指针,rxInit()方法将该指针保存在g_pDesc静态成员中。
newOdRxClass()函数的定义如下:

FIRSTDLL_EXPORT OdRxClass* newOdRxClass(       /* Returns the raw pointer the class describing instance */
  const OdString& szClassName,                 /* It is the class name that will be returned by the name() method */
  OdRxClass* pBaseClass,                       /* It is the pointer to the parent class describing instance */
  OdPseudoConstructorType pConstr,             /* It is the pointer to pseudo-constructor function */
  int DwgVer,                                  /* It is the dwg-version number defined by the DwgVersion enumeration */
  int MaintVer,                                /* It is the maintain version number defined by the MaintReleaseVer enumeration */
  int nProxyFlags,                             /* It is the mask of the proxy flags */
  const OdString& szDxfName,                   /* It is the dxf-class name */
  const OdString& szAppName                    /* It is the application class name */
  AppNameChangeFuncPtr fNameChangeFunc = NULL, /* It is a pointer to the callback function */
  int nCustomFlags = 0                         /* It is the mask of the custom flags */
)

rxInit()方法是重载的,有两个实现。rxInit()的第一个实现没有参数,并且创建了一个没有回调的类描述实例。指向回调函数的指针为NULLrxInit的第二个实现(AppNameChangeFuncPtr)需要一个指向回调函数的指针,这个回调函数在将绘图保存到文件时调用,并且要为自定义类编写类描述实例表示的应用程序类名。
在默认实现中,rxUninit()方法使用deleteOdRxClass()全局函数从类字典中删除关于类的项,并在引用计数器变为0时释放描述实例的类。
函数的定义如下:

FIRSTDLL_EXPORT void deleteOdRxClass(OdRxClass* pClass)          /* The class describing instance to be removed */

当你实现你自己的类,使用以下步骤:

  1. 在类定义的“public:”部分使用ODRX_DECLARE_MEMBERS宏声明标准的RTTI方法。
  2. 使用c代码中的ODRX_NO_CONS_DEFINE_MEMBERS、ODRX_CONS _DEFINE_MEMBERS、ODRX_DEFINE_MEMBERS、ODRX_DXF_DEFINE_ MEMBERS、ODRX_DXF_ CONS_DEFINE_MEMBERS宏创建RTTI方法的标准实现。
  3. 在初始化应用程序之后并在创建类的实例之前,使用其rxInit()方法在程序中注册该类。
  4. 获取描述实例的类,并使用其方法在运行时获取关于该类的信息。
  5. 在使用它之后和在取消初始化应用程序之前,使用它的rxUninit()方法在程序中取消注册该类。
    为了获得对象实例的类描述实例要么使用isA()虚方法返回原始指针,指向描述OdRxClass类型实例的类,这个类是与对象实例动态关联的,或者使用desc()静态方法返回原始指针,指向描述OdRxClass类型实例的类,该类静态地与对象实例相关联。
    例如,要注册一个用户定义的类xSomeObj,可以直接从OdRxObject类派生xSomeObj类。要声明标准的RTTI方法,请使用ODRX_DECLARE_MEMBERS宏。要实现标准的RTTI方法,可以使用ODRX_DEFINE_MEMBERS宏来指定所有运行时参数。为了测试这个类,下面的示例创建它的实例,然后打印它的运行时类型信息。主模块具有以下实现(粗体标记了上面列出的步骤)
#include "OdaCommon.h"
#include "OdToolKit.h"
#include "..\\..\\Teigha.dwg\\Extensions\\ExServices\\ExHostAppServices.h" 
#include "..\\..\\Teigha.dwg\\Extensions\\ExServices\\ExSystemServices.h"
class MyApp : public ExSystemServices 
{
 protected:
  ODRX_USING_HEAP_OPERATORS(ExSystemServices);
 public:
   MyApp() {};
};
class xSomeObj : public OdRxObjectImpl<OdRxObject>
{
 public:
   ODRX_DECLARE_MEMBERS(xSomeObj);                               // Step 1 - Declaring of the RTTI methods             
   xSomeObj() {};
   ~xSomeObj() {};
};
typedef OdSmartPtr<xSomeObj> xSomeObjPtr;
ODRX_DEFINE_MEMBERS(xSomeObj, OdRxObject, NEWOBJ_CONSTR, OdDb::vAC18, OdDb::kMReleaseCurrent, 
                    0x82, "MyRxClass", "acMYCLASS", "MyApp");    // Step 2 - Implementing of the RTTI methods
#include <conio.h>
int main()
{
  OdStaticRxObject<MyApp> svcs;
  odInitialize(&svcs);
  xSomeObj::rxInit();                                            // Step 3 - Registering the user-defined class
  xSomeObjPtr pObj = xSomeObj::createObject();                   // Create an object instance of the user-defined class
  OdRxClass* pCls = pObj->isA();                                 // Step 4 - Get the class describing instance
                                                                 //          and information about this class
  OdDb::MaintReleaseVer nMaintVer;
  OdDb::DwgVersion nDwgVer = pCls->getClassVersion(&nMaintVer);  // Get the maintain and dwg version numbers
  odPrintConsoleString(L"\\nObject Instance [%x]", pObj.get());
  odPrintConsoleString(L"\\nClass Describing Instance [%x]", pCls);
  odPrintConsoleString(L"\\nClass Name = %s", pCls->name().c_str());
  odPrintConsoleString(L"\\nProxy flags = %x", pCls->proxyFlags());
  odPrintConsoleString(L"\\nCustom flags = %x", pCls->customFlags());
  odPrintConsoleString(L"\\nDXF Class Name = %s", pCls->dxfName().c_str());
  odPrintConsoleString(L"\\nParent Class Name = %s", pCls->myParent()->name().c_str());
  odPrintConsoleString(L"\\nApplication Class Name = %s", pCls->appName().c_str());
  odPrintConsoleString(L"\\nDWG version = %d \\nMaintain version = %d", nDwgVer, nMaintVer);
  getch();
  xSomeObj::rxUninit();                                          // Step 5 - Unregistering the user-defined class
  odUninitialize();
  return 0;
}

结果:

Object Instance [135a45]
Class Describing Instance [e2cdb8]
Class Name = MyRxClass
Proxy flags = 82
Custom flags = 0
DXF Class Name = acMYCLASS
Parent Class Name = OdRxObject
Application Class Name = MyApp
DWG version = 25
Maintain version = 6

如果使用以下宏实现方法:
ODRX_CONS_DEFINE_MEMBERS(xSomeObj, OdRxObject, NEWOBJ_CONSTR);
结果为:

Object Instance [135a45]
Class Describing Instance [e2cdb8]
Class Name = xSomeObj
Proxy flags = 0
Custom flags = 0
DXF Class Name =
Parent Class Name = OdRxObject
Application Class Name =
DWG version = 0
Maintain version = 0

Understanding the Dictionary of Classes

RTTI实现包含一个特殊的全局dictionary对象,它存储在应用程序中注册的所有类的列表。该字典将描述实例的类的指针与类名相关联。关联<指针名>是类字典的项。类名是关键字。此外,字典将整数号与作为类ID的每个项匹配。所有项构成描述实例的类的集合;实例被放在空闲内存中。
在这里插入图片描述
当应用程序使用rxInit()方法注册类时,newOdRxClass()全局函数创建一个描述实例的新类,并在类字典中添加一个与类名相同的关键字新项。当应用程序使用rxUninit()方法注销该类时,deleteOdRxClass()全局函数释放描述实例的类并从类字典中删除它的项。
要获得类字典,使用odrxClassDictionary()全局函数来返回已注册类字典的智能指针。例如:

OdRxDictionaryPtr  pClsDict = odrxClassDictionary();

类字典可以使用类名或类ID操作项。如果知道类名(键),就可以得到类ID。如果知道类ID,就可以得到类名(键)。如果知道类名或类ID,就可以获得描述类的实例。您还可以检查类字典中是否存在类名或类ID
要获取已知类名的类ID,可以使用idAt()方法,该方法需要类名作为OdString类型的参数,并将类ID作为OdUInt32类型的值返回。例如

odPrintConsoleString(L"\\nThe key \\"%s\\" has the ID = %d", L"OdValue", pClsDict->idAt(L"OdValue"));

要获取已知类ID的类名,可以使用keyAt()方法,该方法需要类ID作为OdUInt32类型的参数,并返回OdString类型的类名。例如:

odPrintConsoleString(L"\\nThe ID %d has the key \\"%s\\"", 10, pClsDict->keyAt(10).c_str());

如果指定的类ID在类字典中不存在,keyAt()方法将生成aNotApplicable异常。如果指定的类名在类字典中不存在,则idAt()方法返回一个(1)值。
要检查类名或类ID是否存在于字典中,可以使用has()方法,该方法需要类名或类ID作为参数,如果键或ID存在于字典中,则返回True,否则返回False。例如:

void PrintKeyExist(const OdString& key)
{
  OdRxDictionaryPtr  pClsDict = odrxClassDictionary();
  odPrintConsoleString(L"\\nThe dictionary %s the \\"%s\\" key", ((pClsDict->has(key) == true) ? L"has" : L"does not have"), key);
}  
void PrintIdExist(const OdUInt32 id)
{
  OdRxDictionaryPtr  pClsDict = odrxClassDictionary();
  odPrintConsoleString(L"\\nThe dictionary %s the ID = %d", ((pClsDict->has(id) == true) ? L"has" : L"does not have"), id);
}

has() 方法或idAt()方法搜索类名时,默认情况下搜索不区分大小写(“MyClass”和“MyClass”是等价的)。isCaseSensitive()方法在搜索区分大小写的键时返回True,在不区分大小写的键时返回False。例如:

odPrintConsoleString(L"\\nThe finding of keys is case-%s", ((pClsDict->isCaseSensitive()) ? L"sensitive" : L"insensitive"));

要获得注册类的数量,可以使用numEntries()方法,该方法没有参数,并以整数值的形式返回项的数量。例如:

odPrintConsoleString(L"\\nThe dictionary contains %d classes", pClsDict->numEntries());

要获取已知类名或类ID的类描述实例,请使用getAt()方法,该方法需要类名或类ID作为参数,并返回非类型化的智能指针以指向描述实例的类。例如:

void PrintClassInfo(const OdUInt32 id)
{
  OdRxDictionaryPtr  pClsDict = odrxClassDictionary();
  if(pClsDict->has(id) == false)
  {
    odPrintConsoleString(L"\\nID = %d  is not found in the dictionary", id);
  }
  else
  { OdRxClassPtr pClsPtr = (OdRxClassPtr) pClsDict->getAt(id);
    odPrintConsoleString(L"\\nClass Describing Instance [%x]", pClsPtr);
    odPrintConsoleString(L"\\nClass Name = %s", pClsPtr->name().c_str());
    odPrintConsoleString(L"\\nProxy flags = %x", pClsPtr->proxyFlags());
    odPrintConsoleString(L"\\nDXF Class Name = %s", pClsPtr->dxfName().c_str());
    odPrintConsoleString(L"\\nParent Class Name = %s", pClsPtr->myParent()->name().c_str());
    odPrintConsoleString(L"\\nApplication Class Name = %s", pClsPtr->appName().c_str());
  }
}

要遍历类dictionary,使用newIterator()方法创建的dictionary迭代器,因为它在遍历dictionary主题的项时进行了描述。
dictionary还从OdRxDictionary类继承以下内容:

  • putAt() method — 在类字典中添加新项将指定的描述实例的类与该类关联的名字。
  • resetKey()method — 为指定的ID设置指定的键而不是旧键。
  • remove() method — 从类字典中删除具有指定键或ID的项,但不删除关联的描述实例的类。
    您不应该使用这些方法来修改类字典,因为它可能会干扰寄存器和注销过程,这些过程对rxInit()和rxUninit()静态方法实现的类执行附加操作。类的rxInit()方法必须注册类并将其项添加到类字典中。类的rxUninit()方法必须取消注册该类,并从类字典中删除其项。如果直接修改程序中的类字典,则可能发生冲突和错误。

Belonging to an Instance of a Class

OdRxObject类声明queryX()isKindOf()x()方法,这些方法允许开发人员检查实例是属于指定类还是属于指定类的子类。这些方法需要一个指向类的原始指针,将实例描述为一个参数;它们在行为和返回结果上有所不同。开发人员可以使用这些方法来验证是否可以将指针转换为指定的实例、应用方法和函数、或者根据指定实例的类类型选择数据处理。
queryX()方法是一个虚拟方法,它在实例是来自或属于指定类的对象时返回实例的地址,否则返回NULLODRX_DEFINE_RTTI_MEMBERS(ClassName, ParentClass)宏自动为使用它的每个类创建queryX()方法的实现。这个宏需要类名和父类名,并创建queryX()方法的以下实现:

OdRxObject* ClassName::queryX(const OdRxClass* pClass) const
{ 
  return ::odQueryXImpl<ClassName,ParentClass>(this, pClass); 
}

odQueryXImpl()全局函数是自动创建验证指定类和父类的实现的模板。odQueryXImpl()函数的模板具有以下实现:

template <class Class, class Parent>
OdRxObject* odQueryXImpl(const Class* pThis, const OdRxClass* pClass)
{
  ODA_ASSERT(pClass!=0);
  OdRxObject* pObj = 0;
  if(pClass == Class::desc())
  {
    pObj = (OdRxObject*) pThis;
    pObj->addRef();
  }
  else
  {
    pObj = Class::desc()->getX(pClass).detach();
    if(!pObj)
      pObj = pThis->Parent::queryX(pClass);
  }
  return pObj;
}

函数的作用是:通过父类的queryX()方法递归定义当前类所属的类。开发人员不需要重新定义queryX()方法。开发人员可以使用结果作为指针,将其转换为指定的类或验证该类。
isKindOf()方法是一种非虚方法,当实例是派生自或属于指定类的对象时,它返回True,否则返回False。派生自OdRxObject类的类继承此方法;开发人员不能重新定义它。isKindOf()方法使用queryX()方法检查实例是否属于指定的类,并在queryX()方法返回NULL时返回False。该方法创建非类型化的智能指针,并尝试将queryX()方法返回的实例附加到它。如果queryX()方法返回实例的地址,则附件成功,isKindOf()方法返回TrueisKindOf()方法有以下实现。

bool isKindOf(const OdRxClass* pClass) const
{
  OdRxObjectPtr pRes;
  pRes.attach(queryX(pClass));
  return (!pRes.isNull());
}

x()方法是一个虚拟方法,当实例是派生自或属于指定类的对象时,或者该方法生成eNotThatKindOfClass异常时,该方法返回实例的地址。开发人员可以在调用此方法时使用try catch语句在程序中捕获此异常。x()方法使用queryX()方法来检查它是否属于这个类,并在queryX()方法返回NULL时生成异常。x()方法具有以下实现:

OdRxObject* OdRxObject::x(const OdRxClass* pClass) const
{
  OdRxObject* pRes = 0;
  if(pClass)
  {
    pRes = queryX(pClass);
    if(!pRes) throw OdError_NotThatKindOfClass(isA(), pClass);
  }
  else throw OdError(eInvalidInput);
  return pRes;
}

OdRxClass类声明isDerivedFrom()方法还允许开发人员来检查一个类是否属于指定的类或子类。这种方法也需要一个原始指针类描述实例作为参数。方法返回True时,类是来自或属于指定的类,或者返回FalseisDerivedFrom()方法分析类的层次结构描述实例使用父类指针。这个方法适用于类描述实例后,可以使用注册类。isDerivedFrom()方法有以下的实现。

bool OdRxClass::isDerivedFrom(const OdRxClass* pClass) const
{
  const OdRxClass* pCurr = this;
  while(pCurr)
  {
    if(pCurr == pClass) return true;
    pCurr = pCurr->myParent();
  }
  return false;
}

注意:要使用queryX()isKindOf()x()isDerivedFrom()方法,必须先执行寄存器过程。使用这些方法只能检查注册的类。
例如,考虑三个类:ClsX、ClsY、ClsZClsX类派生自OdRxObject类。ClsY类派生自ClsX类。ClsZ类派生自ClsX类。示例代码如下:

#include "OdaCommon.h"
#include "OdToolKit.h"
#include "..\\..\\Teigha.dwg\\Extensions\\ExServices\\ExHostAppServices.h"
#include "..\\..\\Teigha.dwg\\Extensions\\ExServices\\ExSystemServices.h"
class MyApp : public ExSystemServices 
{
 protected:
   ODRX_USING_HEAP_OPERATORS(ExSystemServices);
 public:
   MyApp() {};
};
class ClsX : public OdRxObjectImpl<OdRxObject>
{
 public:
   ODRX_DECLARE_MEMBERS(ClsX);
   ClsX() {};
};
ODRX_CONS_DEFINE_MEMBERS(ClsX, OdRxObject, NEWOBJ_CONSTR);
class ClsY : public ClsX
{
 public:
   ODRX_DECLARE_MEMBERS(ClsY);
   ClsY() {};
};
ODRX_CONS_DEFINE_MEMBERS(ClsY, ClsX, NEWOBJ_CONSTR);
class ClsZ : public ClsX
{
 public:
   ODRX_DECLARE_MEMBERS(ClsZ);
   ClsZ() {};
};
ODRX_CONS_DEFINE_MEMBERS(ClsZ, ClsX, NEWOBJ_CONSTR);
int main()
{
  OdStaticRxObject<MyApp> svcs;
  odInitialize(&svcs);
  ClsX::rxInit();
  ClsY::rxInit();
  ClsZ::rxInit();
  odPrintConsoleString(L"\\nIs ClsY derived from ClsX => %s", ((ClsY::desc()->isDerivedFrom(ClsX::desc())) ? L"true" : L"false") );
  odPrintConsoleString(L"\\nIs ClsZ derived from ClsX => %s", ((ClsZ::desc()->isDerivedFrom(ClsX::desc())) ? L"true" : L"false") );
  odPrintConsoleString(L"\\nIs ClsZ derived from ClsY => %s", ((ClsZ::desc()->isDerivedFrom(ClsY::desc())) ? L"true" : L"false") );
  odPrintConsoleString(L"\\nIs ClsX derived from ClsY => %s", ((ClsX::desc()->isDerivedFrom(ClsY::desc())) ? L"true" : L"false") );
  OdRxObjectPtr pClsX = ClsX::createObject();
  OdRxObjectPtr pClsY = ClsY::createObject();
  OdRxObjectPtr pClsZ = ClsZ::createObject();
  odPrintConsoleString(L"\\nQuery (ClsY => ClsX) = %x", pClsY->queryX(ClsX::desc()) );
  odPrintConsoleString(L"\\nQuery (ClsZ => ClsX) = %x", pClsZ->queryX(ClsX::desc()) );
  odPrintConsoleString(L"\\nQuery (ClsZ => ClsY) = %x", pClsZ->queryX(ClsY::desc()) );
  odPrintConsoleString(L"\\nQuery (ClsX => ClsY) = %x", pClsX->queryX(ClsY::desc()) );
  odPrintConsoleString(L"\\nIs ClsY %s to ClsX", ((pClsY->isKindOf(ClsX::desc())) ? L"belongs" : L"does not belong") );
  odPrintConsoleString(L"\\nIs ClsZ %s to ClsX", ((pClsZ->isKindOf(ClsX::desc())) ? L"belongs" : L"does not belong") );
  odPrintConsoleString(L"\\nIs ClsZ %s to ClsY", ((pClsZ->isKindOf(ClsY::desc())) ? L"belongs" : L"does not belong") );
  odPrintConsoleString(L"\\nIs ClsX %s to ClsY", ((pClsX->isKindOf(ClsY::desc())) ? L"belongs" : L"does not belong") );
  try {
    odPrintConsoleString(L"\\nIs ClsY kind of ClsX => %s", ((pClsY->x(ClsX::desc()) != NULL) ? L"true" : L"false") );
  }
  catch(OdError_NotThatKindOfClass err) 
  {
    odPrintConsoleString(L"\\nException %d - %s", err.code(), err.description().c_str());
  }
  try {
    odPrintConsoleString(L"\\nIs ClsZ kind of ClsY => %s", ((pClsZ->x(ClsY::desc()) != NULL) ? L"true" : L"false") );
  }
  catch(OdError_NotThatKindOfClass err)
  {
    odPrintConsoleString(L"\\nException %d - %s", err.code(), err.description().c_str());
  }
  ClsZ::rxUninit();
  ClsY::rxUninit();
  ClsX::rxUninit();
  odUninitialize();
  return 0;
}

检查ClsXClsYClsZ类会得到以下结果:

Is ClsY derived from ClsX => true
Is ClsZ derived from ClsX => true
Is ClsZ derived from ClsY => false
Is ClsX derived from ClsY => false
Query (ClsY => ClsX) = 135a3d0
Query (ClsZ => ClsX) = 135a3e0
Query (ClsZ => ClsY) = 0
Query (ClsX => ClsY) = 0
ClsY belongs to ClsX
ClsZ belongs to ClsX
ClsZ does not belong to ClsY
ClsX does not belong to ClsY
Is ClsY kind of ClsX => true
Exception 63 - Object of class ClsZ can't be cast to ClsY.

Functionality of RTTI

OdRxClass类支持标准的引用计数功能,并提供RTTI功能,该功能仅定义自OdRxObject类派生的注册类。类必须在其自己的公共部分中使用ODRX_DECLARE_MEMBERS宏声明RTTI方法,并在cppc -code中使用ODRX_**_DEFINE_MEMBERS_** 宏定义它们的实现。如果一个类没有注册,它的RTTI方法会生成eNotApplicable异常。
例如,下面的xMyCls类派生自OdRxObject类,具有“MyClass”类名、“acMYCLASSdxf类名、“MyApp”应用程序类名、R14 dwg版本、2发布版本和kEraseAllowed &kCloningAllowed代理旗帜。xMyCls类必须有以下定义:

#include "OdaCommon.h"
#include "OdToolKit.h"
#include "..\\..\\Teigha.dwg\\Extensions\\ExServices\\ExHostAppServices.h"
#include "..\\..\\Teigha.dwg\\Extensions\\ExServices\\ExSystemServices.h"
class xMyCls : public OdRxObjectImpl<OdRxObject>
{
 public:
   ODRX_DECLARE_MEMBERS(xMyCls);                     // Declaring of the RTTI methods
   xMyCls() {};
   ~xMyCls() {};
};                                                   // Implementing of the RTTI methods
ODRX_DEFINE_MEMBERS(xMyCls, OdRxObject, NEWOBJ_CONSTR, kDHL_1014, kMRelease2, 0x81, "MyClass", "acMYCLASS", "MyApp");

在应用RTTI方法之前,必须使用rxInit()静态方法在主程序中注册xMyCls类。要获取描述实例的类,使用desc()静态方法返回OdRxClass类型的智能指针,该指针引用静态地与这个注册类关联的描述实例的类。

class MyApp : public ExSystemServices 
{
 protected:
   ODRX_USING_HEAP_OPERATORS(ExSystemServices);
   MyApp() {};
};
void main()
{
   OdStaticRxObject<MyApp> svcs;
   odInitialize(&svcs);
   xMyCls::rxInit();                                 // Registering of the class
	
   OdRxClassPtr pCls = xMyCls::desc();               // Getting of the class describing instance
	
   // Here, past a one of cpp-codes described below 
	
   xMyCls::rxUninit();                               // Unregistering of the class
   odUninitialize();
}	

要获取描述实例的类的地址,请使用返回的智能指针的get()方法。例如:

odPrintConsoleString(L"\\nThe class describing instance = %x", pCls.get());                // Prints:  = 14A208

要获取类名,请使用name()方法,该方法将已注册类的名称作为OdString类型的字符串返回。例如:

odPrintConsoleString(L"\\nThe class name = %s", pCls->name().c_str());                     // Prints:  = MyClass

要获取dxf类名,可以使用dxfName()方法,该方法将dxf类名作为OdString类型的字符串返回。例如:

odPrintConsoleString(L"\\nThe dxf class name = %s", pCls->dxfName().c_str());              // Prints:  = acMYCLASS

要获取应用程序类名,请使用appName()方法,该方法将应用程序的名称作为OdString类型的字符串返回。例如:

odPrintConsoleString(L"\\nThe application class name = %s", pCls->appName().c_str());      // Prints:  = MyApp

要获得父类,可以使用myParent()方法,该方法将原始指针返回到描述实例的类,该实例将父类描述为OdRxClass类型的指针。例如:

odPrintConsoleString(L"\\nThe parent class name = %s", pCls->myParent()->name().c_str());  // Prints:  = OdRxObject

要获取代理标志,使用proxyFlags()方法,该方法返回一个位掩码作为OdUInt32类型的整数值。例如:

odPrintConsoleString(L"\\nThe proxy flags = %x", pCls->proxyFlags());                      // Prints:  = 0x81

要获取自定义标志,请使用customFlags()方法,该方法将一个位掩码作为OdUInt32类型的整数值返回。例如:

odPrintConsoleString(L"\\nThe custom flags = %x", pCls->customFlags());                      // Prints:  = 0

要获得维护版本和.dwg文件版本,使用getClassVersion()方法,该方法返回.dwg文件版本号,并需要一个原始指针指向该方法保存维护版本号的变量。MaintReleaseVer枚举定义维护版本。DwgVersion枚举定义.dwg文件版本。例如:

OdDb::MaintReleaseVer nMaintVer;
OdDb::DwgVersion nDwgVer = pCls->getClassVersion(&nMaintVer);
odPrintConsoleString(L"\\nMaintain version = %d", nMaintVer);                              // Prints:  = 2
odPrintConsoleString(L"\\nDWG version = %d", nDwgVer);                                     // Prints:  = 21

要获取类所在的模块,请使用module()方法,该方法返回指向模块的原始指针。例如:

OdRxModule pModule = pCls->module();
If(pModule != NULL)
  odPrintConsoleString(L"\\nThe module name = %s", pModule->moduleName().c_str());

要获取在保存已注册对象时调用的回调函数,请使用返回回调函数指针的appNameCallbackPtr()方法。例如:

AppNameChangxFuncPtr pFunc = pCls->appNameCallbackPtr();
If(pFunc != NULL)
  odPrintConsoleString(L"\\nThe callback function is set");

注意:自定义类可以根据其保存到的文件格式版本更改其应用程序名称。这种更改是使用作为参数传递给rxInit()函数的回调函数指针实现的,只有保存到文件(.dwg或.dxf)。例如,保存为2004格式的自定义对象可以保存为应用程序名称“Aec40”,保存为2007文件格式的应用程序名称“Aec70”,等等。appName()返回的运行时应用程序名称总是相同的。
要检查xMyCls类是否派生自OdRxObject类,可以使用isDerivedFrom()方法,该方法需要一个原始指针指向将实例描述为参数的类,当类派生自指定类时返回True,否则返回False。例如:

odPrintConsoleString(L"\\nxMyCls is derived from OdRxObject = %s", 
                    (pCls->isDerivedFrom(OdRxObject::desc())) ? L"true" : L"false");      // Prints:  = true
 
© 版权声明
THE END
喜欢就支持一下吧
点赞338 分享
评论 抢沙发
头像
欢迎您留下宝贵的见解!
提交
头像

昵称

取消
昵称表情代码图片

    暂无评论内容