当前位置: 首页 > news >正文

COM接口规则的存在是有原因的

可能有些人认为接口上的 COM 接口规则没有必要设计的那么严格,但我想说的是,这些规则的存在是有原因的。

假设你在你的产品代码中新增加了版本号为 N 的接口,由于这个接口是内部使用的,没有任何公开文档。所以你可以随意修改它,而不会打破任何不兼容性。

但是需要注意的是,如果你修改一个接口,则必须要生成一个新的接口标识符(IID),因为一个接口标识符唯一标识了这个接口(正如它的名字所暗示的那样)。

以上这条规则,即使是对于内部接口也是一样。

假设你决定不遵循这一规则,在 N + 1 版本的接口中继续使用 N 版本相同的 IID,由于这是一个内部使用的借口,应该不会造成什么大影响。

直到你需要为这两个版本编写一个补丁,事情就不太妙了。

这个补丁会出现这样的问题:它可以调用 IUnknown::QueryInterface 方法并传入这个 IID,COM 库会返回一些东西。但是你不会知道返回的是 N 版本的接口,还是 N + 1 版本的接口。如果你没有意识到这一点,则你的补丁代码很可能会假设返回的是 N + 1 版本的接口,这个时候,如果实际的接口是 N 版本的话,一些奇怪的事情就会发生。

调试这类问题不太好玩,相信我,修复它也不太容易。

你的补丁必须使用其他一些提示来决定它实际返回的接口。如果程序以前已打过补丁,则需要具有每个补丁的版本号,以便确定所拥有的接口版本。
请注意,此依赖项可以隐藏在其他接口后面。考虑下面的代码:

>> 请移步至 topomel.com 以查看图片 <<

假设你要向 IColorInfo 接口添加一个新方法:

>> 请移步至 topomel.com 以查看图片 <<

由于改变了接口,但同时也改变了IID,所以一切都很好,对吧?
非也!

IGraphicImage 接口依赖于 IColorInfo 接口。当你修改 IColorInfo 接口时,也隐式更改了
IGraphicImage::GetColorInfo 方法,因为返回的接口现在是 N + 1 版本的 IColorInfo 接口。

考虑使用 N + 1 版本的头文件编写的补丁程序。

>> 请移步至 topomel.com 以查看图片 <<

如果针对 N 版本运行,则对
IGraphicImage::GetColorCount 的调用将返回 N 版本的 IColorInfo,并且该版本不支持 IColorInfo::AdjustColor 方法。但无论如何你调用它。结果就是: 访问 N 版本的虚函数表的结尾并造成访问违规。

快速的解决方案是,修改 IGraphicImage 的 IID,以反映它所依赖的 IColorInfo 接口上的更改。

>> 请移步至 topomel.com 以查看图片 <<

更可靠的解决方法是,修改
IGraphicImage::GetColorInfo 方法,以便传递要接收的接口。

>> 请移步至 topomel.com 以查看图片 <<

这允许更改 IGraphicImage 所依赖的接口,而无需更改 IGraphicImage 接口本身。当然,实现需要改变以响应IID_IColorInfo 的新值。但是现在调用者可以放心,因为当它请求接口时,它实际上是在获取它,而不是巧合地具有相同名称的其他东西。

总结

我从过去伤痕累累的经历中只学会了一件事: 接口一经对外发布,就只能扩展,不能再修改。你得为你的客户想想。
成也 COM,败也 COM。

最后

Raymond Chen的《The Old New Thing》是我非常喜欢的博客之一,里面有很多关于Windows的小知识,对于广大Windows平台开发者来说,确实十分有帮助。
本文来自:《The COM interface contract rules exist for a reason》

 

http://www.lryc.cn/news/68718.html

相关文章:

  • 并行分布式计算 并行计算性能评测
  • [网络安全]XSS之Cookie外带攻击姿势及例题详析
  • Angular之创建项目报错:setTimeout is not defined
  • python实现神经网络之---构建神经元模型1(python3.7)
  • 前端面试题 —— JavaScript (三)
  • 【openGauss】一键编译openGauss5.0+dolphin,体验新增的mysql兼容特性
  • 【LeetCode - 每日一题】1073. 负二进制数相加 (2023.05.18)
  • 软件上线会面临哪些缺陷?这四种你一定很熟悉
  • html监听界面被隐藏或显示
  • Springboot启动失败 DB连不上竟然是maven配置的问题
  • P9234 [蓝桥杯 2023 省 A] 买瓜 题解
  • ThingsBoard自定义分发节点duplicate to related
  • vim自动更新ctags与taglist
  • linux查看日志常用命令,动态日志命令
  • 分段存储管理方式
  • 将nacos从本地切换到远程服务器上时报错:客户端端未连接,Client not connected
  • 系统掌握入河排污口设置论证技术、方法及报告编制框架
  • 服务端渲染
  • 干货丨警惕!14个容易导致拒稿的常见错误
  • Web基础 ( 二 ) CSS
  • MSQL系列(一) Mysql实战-索引结构 二叉树/平衡二叉树/红黑树/BTree/B+Tree
  • 理论力学专题:张量分析
  • 索引失效情况
  • pv操作练习题
  • 【小菜鸡刷题记】--字符串篇
  • Sonar加入jenkins流水线
  • FSW26现金回收RS FSW43 信号和频谱分析仪
  • GraphPad Prism 9.5.1 for Mac 操作简便功能强大且实用的医学绘图分析工具
  • 六. Activity启动模式
  • 本机连接aws的ec2时报错:所选用户的用户密钥未在远程主机上注册