OCCT源码阅读(一)

前言

        代码路漫漫,五花八门的技术时常让我无法抉择,不清楚怎么样才能继续进阶。或许学习的深度不够,学习的毅力不足。无奈学习路上,鲜有志同道合的伙伴交流未来何去何从,只能自己继续探索。虽不知道要去哪,但是只要不停下来应该都会是进步的吧。千里之行始于足下,开始认真的阅读源码吧。

        相比阅读源码,更难的可能是写阅读源码的笔记......懒写博客是一种坏习惯,需要克服!

一、TKernel

简介:对基础数据类型、容器、异常进行封装,提供一些编码、文件系统、操作系统级别数据定义、接口封装。

1.文件目录概述

文件夹名称概述
FlexLexer用于定义由 flex 生成的词法分析器类的接口和实现。
FSD代表 File System Data,用于处理文件系统中的数据操作。
Message提供消息传递和日志记录的功能。
NCollection提供通用的数据结构和容器类,例如数组、链表和向量。
OSD代表 Operating System Dependent,处理操作系统相关的功能,如文件操作和时间管理。
Plugin提供插件机制,用于扩展应用程序的功能。
Quantity处理几何和物理量,例如颜色、角度和长度。
Resource用于管理应用程序资源。
Standard提供基本的数据类型和实用工具,如布尔值、整数和字符串。
StdFail提供标准的异常处理和错误管理机制。
Storage提供数据持久化和存储的功能。
TCollection提供集合类和容器,用于存储和管理对象。
TColStd提供标准集合类,例如数组和序列。
TShort提供短整数类型的数据结构和操作。
Units处理单位和度量转换。
UnitsAPI提供单位处理的应用程序接口(API)。
UnitsMethods提供处理单位和度量转换的具体方法。

一般的开源项目为了支持跨平台必要的数据结构都是需要自己封装的,看起来很高大上,实则也很有水平......但就是没啥太大的价值去仔细研究,所以在这里我就不对其中的数据结构进行仔细的分析了。类似的异常处理、编码处理、字符串帮助方法就跳过了,如果在后面别的库碰到了需要看懂这些才能理解,那就再补充。下边介绍一些我觉得有意思的设计。

2.核心设计

(1)插件机制

先看看源码文件:

插件类定义:

class Plugin 
{
public:
  // 实现了通过GUID加载插件的方法
  Standard_EXPORT static Handle(Standard_Transient) Load (const Standard_GUID& aGUID, const Standard_Boolean theVerbose = Standard_True);  
};

插件载入机制:

  • 插件dll需要定义一个PLUGINFACTORY导出函数,用于插件的加载及卸载

  • Plugin类通过LoadLibrary加载dll后,通过GetProcAddress获取PLUGINFACTORY方法得到插件的ServiceFactory

插件实例定义:

// 定义插件宏,每个插件都需要通过宏实现一个PLUGINFACTORY方法
#define PLUGIN(name) \
extern "C" Standard_EXPORT Standard_Transient* PLUGINFACTORY(const Standard_GUID& aGUID) { \
   return const_cast<Standard_Transient*>(name::Factory(aGUID).get()); \
}
​
// 插件类需要定义一个Factory(Draw_Interpretor& theDI)方法
// 在方法中给解释器添加命令,命令会通过Tcl对进行管理,可以提供控制台调用方法的效果

(2)消息(日志)机制

消息分发类:

// 消息接口类
class Message
{
    // 先确定一个消息的等级权重,返回一个字符流,通过Flush写入消息
    static Message_Messenger::StreamBuffer Send(Message_Gravity theGravity)
    {
      return DefaultMessenger()->Send (theGravity);
    }
​
    // 确定消息内容、消息权重等级,直接发送消息
    static void Send(const TCollection_AsciiString& theMessage, Message_Gravity theGravity)
    {
      DefaultMessenger()->Send (theMessage, theGravity);
    }
}
​
// 消息邮递类,管理了很多个Message_Printer类,负责分发消息
class message_Messenger
{
    Standard_EXPORT Standard_Boolean AddPrinter (const Handle(Message_Printer)& thePrinter);
    Standard_EXPORT Standard_Boolean RemovePrinter (const Handle(Message_Printer)& thePrinter);
    
    Standard_EXPORT void Send (const Standard_CString theString,
                           const Message_Gravity theGravity = Message_Warning) const;
    // ...
}

消息处理类:

// 消息处理基类
class Message_Printer
{
    // 获取消息的权重等级
    Message_Gravity GetTraceLevel() const { return myTraceLevel; }
    // 发送消息
    Standard_EXPORT virtual void Send (const Standard_CString theString,
                                   const Message_Gravity theGravity) const;
    // ...
}
​
// 具体的实现类
class Draw_Printer : public Message_Printer;
class Message_PrinterOStream : public Message_Printer;
class Message_PrinterSystemLog : public Message_Printer;
class Message_PrinterToReport : public Message_Printer;

(3)RTTI机制

基类定义:

// 智能指针,类似于std::shared_ptr
template <class T> class handle;
​
// 通过原子变量,提供了类对象引用计数的机制
class Standard_Transient
{
    // 运行时类型识别(RTTI) 
    Standard_EXPORT Standard_Boolean IsInstance(const opencascade::handle<Standard_Type>& theType) const;  
    Standard_EXPORT Standard_Boolean IsKind(const opencascade::handle<Standard_Type>& theType) const;
    
private:
    // 引用计数
    std::atomic_int myRefCount_;
}
​
// 子类示例
DEFINE_STANDARD_HANDLE(Adaptor2d_Curve2d, Standard_Transient)
class Adaptor2d_Curve2d : public Standard_Transient
{
    // 支持RTTI所需接口宏定义
    DEFINE_STANDARD_RTTIEXT(Adaptor2d_Curve2d, Standard_Transient)
}

辅助宏及类型注册流程:

// 定义了定义new、delete、new[]、delete[]行为
# define DEFINE_STANDARD_ALLOC ...
​
// 支持RTTI所需的接口,获取类型描述符、关联父类、运行时类型
#define DEFINE_STANDARD_RTTIEXT(Class,Base) \
public: \
  typedef Base base_type; \
  static const char* get_type_name () { return #Class; OCCT_CHECK_BASE_CLASS(Class,Base) } \
  Standard_EXPORT static const Handle(Standard_Type)& get_type_descriptor (); \
  Standard_EXPORT virtual const Handle(Standard_Type)& DynamicType() const Standard_OVERRIDE;
​
// 在cxx文件中定义头文件所需方法
//! Defines implementation of type descriptor and DynamicType() function
#define IMPLEMENT_STANDARD_RTTIEXT(Class,Base) \
  const Handle(Standard_Type)& Class::get_type_descriptor () { return Standard_Type::Instance<Class>(); } \
  const Handle(Standard_Type)& Class::DynamicType() const { return STANDARD_TYPE(Class); }
​
// 类型标识类
class Standard_Type : public Standard_Transient
{
    template <class T>
    static const Handle(Standard_Type)& Instance()
    {
        return opencascade::type_instance<T>::get();
    }
}
// 类型注册模板类
template <typename T>
class type_instance
{
static Handle(Standard_Type) myInstance;
public:
static const Handle(Standard_Type)& get ();
};
​
template <typename T>
const Handle(Standard_Type)& type_instance<T>::get ()
{
    // 每个类型都对应一个模板类,都有一个类型实例
static Handle(Standard_Type) anInstance =
  Standard_Type::Register (typeid(T), T::get_type_name(), sizeof(T), 
                           type_instance<typename T::base_type>::get());
return anInstance;
}
​
Standard_Type* Standard_Type::Register (const std::type_info& theInfo, const char* theName,
                                        Standard_Size theSize, const Handle(Standard_Type)& theParent)
{
    // 互斥量避免多线程访问aRegistry冲突
    static Standard_Mutex theMutex;
    Standard_Mutex::Sentry aSentry (theMutex);
    
    // 查找注册的映射表中是否存在该类型的实例,存在则返回
    registry_type& aRegistry = GetRegistry();
    Standard_Type* aType = 0;
    auto anIter = aRegistry.find(theInfo);
    if (anIter != aRegistry.end())
        return anIter->second;
​
    // 如果已注册的列表中没有该实例,则创建一个加入到列表
    aType = new Standard_Type (theInfo, theName, theSize, theParent);
    aRegistry.emplace(theInfo, aType);
    return aType;
}

  • 10
    点赞
  • 7
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值