用织梦做领券网站,承德市建设局网站,程序员外包网,紫色网站可能有些人认为接口上的 COM 接口规则没有必要设计的那么严格#xff0c;但我想说的是#xff0c;这些规则的存在是有原因的。
假设你在你的产品代码中新增加了版本号为 N 的接口#xff0c;由于这个接口是内部使用的#xff0c;没有任何公开文档。所以你可以随意修改它但我想说的是这些规则的存在是有原因的。
假设你在你的产品代码中新增加了版本号为 N 的接口由于这个接口是内部使用的没有任何公开文档。所以你可以随意修改它而不会打破任何不兼容性。
但是需要注意的是如果你修改一个接口则必须要生成一个新的接口标识符(IID)因为一个接口标识符唯一标识了这个接口(正如它的名字所暗示的那样)。
以上这条规则即使是对于内部接口也是一样。
假设你决定不遵循这一规则在 N 1 版本的接口中继续使用 N 版本相同的 IID由于这是一个内部使用的借口应该不会造成什么大影响。
直到你需要为这两个版本编写一个补丁事情就不太妙了。
这个补丁会出现这样的问题它可以调用 IUnknown::QueryInterface 方法并传入这个 IIDCOM 库会返回一些东西。但是你不会知道返回的是 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》