`
kuwoleft
  • 浏览: 1075004 次
文章分类
社区版块
存档分类
最新评论

构建自己的C/C++插件开发框架(四)——核心层设计和实现

 
阅读更多

<!-- [if gte mso 9]><xml> <w:WordDocument> <w:View>Normal</w:View> <w:Zoom>0</w:Zoom> <w:PunctuationKerning/> <w:DrawingGridVerticalSpacing>7.8 磅</w:DrawingGridVerticalSpacing> <w:DisplayHorizontalDrawingGridEvery>0</w:DisplayHorizontalDrawingGridEvery> <w:DisplayVerticalDrawingGridEvery>2</w:DisplayVerticalDrawingGridEvery> <w:ValidateAgainstSchemas/> <w:SaveIfXMLInvalid>false</w:SaveIfXMLInvalid> <w:IgnoreMixedContent>false</w:IgnoreMixedContent> <w:AlwaysShowPlaceholderText>false</w:AlwaysShowPlaceholderText> <w:Compatibility> <w:SpaceForUL/> <w:BalanceSingleByteDoubleByteWidth/> <w:DoNotLeaveBackslashAlone/> <w:ULTrailSpace/> <w:DoNotExpandShiftReturn/> <w:AdjustLineHeightInTable/> <w:BreakWrappedTables/> <w:SnapToGridInCell/> <w:WrapTextWithPunct/> <w:UseAsianBreakRules/> <w:DontGrowAutofit/> <w:UseFELayout/> </w:Compatibility> <w:BrowserLevel>MicrosoftInternetExplorer4</w:BrowserLevel> </w:WordDocument> </xml><![endif]--><!-- [if gte mso 9]><xml> <w:LatentStyles DefLockedState="false" LatentStyleCount="156"> </w:LatentStyles> </xml><![endif]--><!-- /* Font Definitions */ @font-face {font-family:宋体; panose-1:2 1 6 0 3 1 1 1 1 1; mso-font-alt:SimSun; mso-font-charset:134; mso-generic-font-family:auto; mso-font-pitch:variable; mso-font-signature:3 680460288 22 0 262145 0;} @font-face {font-family:"/@宋体"; panose-1:2 1 6 0 3 1 1 1 1 1; mso-font-charset:134; mso-generic-font-family:auto; mso-font-pitch:variable; mso-font-signature:3 680460288 22 0 262145 0;} /* Style Definitions */ p.MsoNormal, li.MsoNormal, div.MsoNormal {mso-style-parent:""; margin:0cm; margin-bottom:.0001pt; text-align:justify; text-justify:inter-ideograph; mso-pagination:none; font-size:10.5pt; mso-bidi-font-size:12.0pt; font-family:"Times New Roman"; mso-fareast-font-family:宋体; mso-font-kerning:1.0pt;} /* Page Definitions */ @page {mso-page-border-surround-header:no; mso-page-border-surround-footer:no;} @page Section1 {size:612.0pt 792.0pt; margin:72.0pt 90.0pt 72.0pt 90.0pt; mso-header-margin:36.0pt; mso-footer-margin:36.0pt; mso-paper-source:0;} div.Section1 {page:Section1;} /* List Definitions */ @list l0 {mso-list-id:860239880; mso-list-type:hybrid; mso-list-template-ids:1460539006 -1726047862 67698713 67698715 67698703 67698713 67698715 67698703 67698713 67698715;} @list l0:level1 {mso-level-text:%1、; mso-level-tab-stop:18.0pt; mso-level-number-position:left; margin-left:18.0pt; text-indent:-18.0pt;} ol {margin-bottom:0cm;} ul {margin-bottom:0cm;} --><!-- [if gte mso 10]> <mce:style><!-- /* Style Definitions */ table.MsoNormalTable {mso-style-name:普通表格; mso-tstyle-rowband-size:0; mso-tstyle-colband-size:0; mso-style-noshow:yes; mso-style-parent:""; mso-padding-alt:0cm 5.4pt 0cm 5.4pt; mso-para-margin:0cm; mso-para-margin-bottom:.0001pt; mso-pagination:widow-orphan; font-size:10.0pt; font-family:"Times New Roman"; mso-ansi-language:#0400; mso-fareast-language:#0400; mso-bidi-language:#0400;} --> <!-- [endif]-->

上面一篇文章大致描述了一下插件开发框架整体结构。这篇描述一下核心层的设计和实现。

至于核心层的设计,我想借鉴 一下微内核的思想。核心层只负责实现下面几个功能:

1、 <!-- [endif]-->插件的加载,检测,初始化。

<!-- [if !supportLists]-->2、 <!-- [endif]-->服务的注册。

<!-- [if !supportLists]-->3、 <!-- [endif]-->服务的调用。

<!-- [if !supportLists]-->4、 <!-- [endif]-->服务的管理。


插件的加载,检测,初始化

插件的加载利用linux共享库的动态加载技术。具体的方法可以看一下IBM网站的一篇资料《Linux 动态库剖析》

服务的注册

服务的注册与调用采用表驱动的方法。核心层中维护一个服务注册表。

//插件间交互消息类型
typedef enum __Service_Type
{
Service_Max,

}Service_Type;


//插件用于和其他插件通信接口函数,由插件提供。
typedef PRsp_Ele_Stream (*PF_Invoke_Service_Func)(PReq_Ele_Stream pele_str);


//驱动表
typedef PF_Invoke_Service_Func Service_Drive_Table[Service_Max];

驱动表是一个数组,下标为插件间交互消息类型,成员为插件提供的接收的消息处理函数,由插件初始化的时候,调用插件框架的的注册函数注册到驱动表。

插件的初始化实现为:
//插件用于注册处理的消息类型的函数,由插件框架提供。
typedef RET_RESULT (*PF_Service_Register_Func)(Service_Type service_type);

//插件用于和其他插件通信接口函数,由插件框架提供。
typedef PRsp_Ele_Stream (*PF_Invoke_Service_Func)(PReq_Ele_Stream pele_str);

//插件回复响应函数。插件收到异步请求后,处理完成后,发送响应消息给请求的插件。由插件框架提供
typedef void (*PF_Send_Response_Func)(PRsp_Ele_Stream pele_str);

//初始化插件信息
typedef struct Plugin_Init_St
{
PF_Service_Register_Func register_func;//服务注册函数,要注册一系列的枚举值。插件可以处理的服务枚举值
PF_Invoke_Service_Func invoke_serv_func;//和其他组件交互时,调用的用于和其他组件交互的函数。发送请求消息。
PF_Send_Response_Func send_rsp_func;//再设计一个回复响应消息的接口。收到异步请求后,处理完毕后通知请求模块处理结果。
} Plugin_Init_St, *PPlugin_Init_St;

//初始化插件函数,类似于构造函数。由插件提供,供插件框架加载插件时初始化插件使用。
void PF_Init_Plugin(PPlugin_Init_St pinit_info);

插件在函数PF_Init_Plugin中调用函数register_func来注册插件要处理的消息类型。

服务的调用
//信元结构体
typedef struct Ele_St
{
Ele_Tag tag;
Ele_Length len;
Ele_Value value;
PEle_St next;
}Ele_St, *PEle_St;

//请求消息,信元流格式。
typedef struct Req_Ele_Stream
{
Plugin_ID src_id;//源插件id
Service_Type req_type;//请求类型
PEle_St ele;
} Req_Ele_Stream, *PReq_Ele_Stream;

//响应消息,信元流格式。
typedef struct Rsp_Ele_Stream
{
Plugin_ID dest_id;//目的插件id
Service_Type req_type;//响应对应的请求的类型。
Execute_Result result;//记录执行结果
Execute_Reason reason;//记录执行结果的原因
PEle_St ele;
} Rsp_Ele_Stream, *PRsp_Ele_Stream;

//接收插件调用服务请求函数,由插件提供,入参为请求信元流。返回值为响应信元流,用于同步请求处理。
PRsp_Ele_Stream PF_Receive_Invoke_Proc(PReq_Ele_Stream pele_str);

//插件收到响应消息的处理入口函数,由插件提供。如此为响应信元流。
void PF_Receive_Rsponse_Porc(PRsp_Ele_Stream pele_str);

插件间的依赖关系是通过信元流来实现的。至于信元流的使用在我的另一篇博客《使用信元流(TLVStream)规范、简化模块(C/C++)间交互 》 中有描述。插件对外的接口都是统一的。

如果插件要和其他的插件通信,则调用PF_Init_Plugin函数的传递的服务调用接口: invoke_serv_func。插件框架根据信元流的类型,查找驱动表,找到对应的服务接收函数。插件用函数PF_Receive_Invoke_Proc接受其他插件的请求,此函数是插件想插件框架主动注册到驱动表的。

如果服务时同步的,这直接通过此函数返回,返回的信息在响应信元流中。如果是异步的请求,这插件在处理完成后,通过 send_rsp_func函数来发送响应。

插件的卸载
//卸载插件时调用的函数,类似于析构函数。由插件提供,供插件框架卸载插件时调用。
void PF_Destroy_Func();


分享到:
评论

相关推荐

Global site tag (gtag.js) - Google Analytics