首页 工作计划 工作总结 事迹材料 心得体会 述职报告 疫情防控 思想汇报 自查报告 党建材料 策划方案 教案设计 范文大全
  • 工作计划
  • 工作总结
  • 事迹材料
  • 心得体会
  • 述职报告
  • 疫情防控
  • 思想汇报
  • 自查报告
  • 党建材料
  • 策划方案
  • 教案设计
  • 范文大全
  • 一种轻量级的Win32应用程序二进制接口兼容方案

    时间:2023-05-29 10:25:05 来源:正远范文网 本文已影响 正远范文网手机站

    zoޛ)j馐1he}8he}}ho3]?}1880 1h`0/v[[yBޢ-{uۢ/r]{mʗyh}iݨky设计符合COM标准的框架

    COM(Component Object Model,组件对象模型),是由微软提出的一套软件接口规范,允许来自不同软件供应商的二进制组件,以一种定义良好的方式连接和通信[7]。COM标准使用C++虚函数表来实现对象的二进制兼容,各模块定义统一抽象接口由其它模块调用,将类的接口与实现相分离。其原理如图1所示。

    模块的抽象接口生成全局唯一的虚函数表,提供给其它模块引用。其它模块通过接口指针或引用,取得该模块虚表地址,通过虚表地址结合函数偏移量,解析出模块内函数在内存中的指针,达到跨边界函数调用的目的。

    一般而言,符合COM标准的抽象接口具有如下特征:

    (1)接口是一个纯虚类,含有纯虚函数,且纯虚函数之间不存在函数重载;

    (2)接口中尽量不包含实体函数,若需要使用实体函数则其必须为内联函数;

    (3)对于需要导出的接口函数,其调用约定统一为_stdcall;

    (4)析构函数不能为虚函数,需要额外定义函数用于析构资源;

    遵循以上规则,设计出框架的基类,如图2所示:

    抽象类IObject为所有框架类的基类,其中Destroy为受保护类型的纯虚函数,是模块析构资源的接口,起到替代析构函数的作用。IObject重载了delete操作符,使其调用Destroy函数。当外界对IObject或IObjectOtherA指针使用delete操作符时,将调用Destroy函数。若需要扩展接口,可继承IObject,以提供多种扩展功能,如IObjectOtherA的做法。

    IObjectDelete作为辅助模板类,实现了资源的正确释放。该模板类所有函数均为内联函数,主要用于绑定各类扩展接口如IObjectOtherA等。同时,它实现了Destroy接口,并将其析构函数声明为虚,重载了delete操作符用于真正释放资源。IObject-Delete首先绑定扩展接口,其余IObject的实现类,如IObj ectlmplA等,通过继承IObjectDelete模板类,来实现具体的接口功能。IObjectDelete可以绑定不同接口,相应的也可以有IObjectlmplA、IOb-jectlmplB等不同实现。

    框架调用的顺序图如图3所示,以IObjec-tOtherA为例进行说明。为了更清晰地表示调用关系,图3中IObject、IObjectOtherA和IObjectDelete以虚对象(外框为虚线)表示,在实际内存中均对应IObj ectlmplA对象。在进行对象析构时,在组件外部对基类指针进行delete操作,由于IObject重载了delete操作符,将调用其Destroy方法。此时通过虚函数表映射,跨越边界,映射至IObjectDelete的Destroy实现,在函数体中对this指针进行delete操作,触发对象的析构。此时,由于IObjectDelete类析构函数声明为虚,子类IObjectImplA的析构函数将优先调用,整个对象的析构流程自此开始。

    4 构建STL辅助类

    为了增加新的优化和特性,Win32平台下部分编译器对STL( Standard Template Library,标准模板库)的实现有意打破了不同版本间的二进制兼容性[8]。因此,在使用STL库时,使用不同版本编译器编译的目标文件和静态库不能在一个二进制文件中混用(EXE或DLL),并且不同版本编译的STL二进制对象不能在组件之间作为参数传递。

    STL库在实际编程中,具有方便、快捷的特点。我们通过利用编译器原有的STL库实现,使用上文中提出的框架对其进行二次封装,构建一系列辅助类,实现了Win32平台下STL库的二进制兼容,使其能跨编译器使用。其类图如图4所示:

    图4中主要对STL库中的string.vector和map类进行了二次封装,已能满足基本应用需求。其它标准容器的封装方法与此类似,不再赘述。需特别注意的是,上述辅助类的实现必需是内联实现,且函数的处理过程中不能抛出任何异常,不可使用任何运行期间类型信息( RTTI),只能使用返回值来返回异常状态。

    辅助类的使用分为两种情况:一是从组件外部传递对象至组件内部,此时只需在栈上声明子类对象,再以基类接口指针或接口引用方式,传递给组件内部使用,使用完毕后对象资源将自动释放。另一种是由组件内部传递对象至组件外部,这种情况需针对特定对象提供CreatelObject函数类似的C语言创建接口,返回基类接口指针以供外部使用,并由外部负责该对象资源的释放。

    5 方案效果验证

    运用上述框架构建驱动模块和桩模块,在Win32平台下使用若干较为陈旧的编译器编译驱动和桩模块,通过不同编译器下驱动和桩模块的交叉调用结果,验证方案的可行性和有效性。其结果如表2所示:

    表2中打勾的部分表示一种可用的兼容组合。从表2中可知,除少部分特别老旧的编译器如GCC2.9.5以外,框架在大部分编译器的组合下均能正常使用,基本达到了跨编译器二进制兼容的设计目标。

    6 结论

    详细介绍了一种Win32应用程序二进制兼容接口设计方法,利用COM技术的核心本质,继而建立了Win32平台下二进制兼容的程序框架,形成了一整套解决方案。该方案成功让组件在大部分编译器下达到二进制级别的兼容,實现了跨边界、跨编译器调用的目标,同时较COM组件更简单、更轻量级。本方案的不足之处在于,缺乏统一的组件注册管理机制,增加了组件调用和资源管理的复杂度,不适用于大型系统的设计。针对大型项目,由于缺乏统一的资源管理方式,该方案会增加程序设计的负担。

    参考文献

    [1] PONOMARENKO A.RUBANOV V.Automatic backward com-patibility analysis of software component binary interfaces[C].Shanghai:2011 IEEE International Conference on Computer Sci-ence and Automation Engineering (CSAE 2011),2011:167- 168.

    [2]WILSON M.ImperfectC++[M].荣耀,刘未鹏,译,北京:人民邮电出版社,2006:110-111.

    [3] BOX D.Essential COM[M]. Massachusetts:Addison WesleyLongman, 1998:14-20.

    [4]粱忠杰,思敏,李婷.COM技术和动态链接库技术的应用研究[J].微计算机应用,2006,27( 6):701-703.

    [5] ISO/IEC 14882:1998, Programming languages C++[S].New York:American National Standards Institute. 1998:76-77.

    [6] ISOflEC 9899:1999,Programming languages C[S].New York:American National Standards Institute. 1999:254-259.

    [7] PUGH B.The component object model: technical overview [EB/0L]. (1994 -12 -1) [2018.3.l].https:///gdicanio/201 6/07/11/the-perils-of-c-interface-dlls/.

    推荐访问:应用程序 兼容 接口 方案 Win32