实现与二进制兼容性

时间:2018-06-21 21:10:21

标签: vba vb6

我有一个VB6 ActiveX DLL,它公开了类INewReport。我向此类添加了一些新方法,并且能够重建它并保持二进制兼容性。

我有第二个DLL,它公开了类clsNewReport,该类使用以下方法实现了第一个类:

Implements RSInterfaces.INewReport

自从我将新方法添加到INewReport以来,我还必须将这些新方法添加到clsNewReport

但是,当我尝试编译第二个DLL时,出现二进制兼容性错误“ ...类在版本兼容组件中实现了接口,但在当前项目中未实现”

enter image description here

我不确定这里发生了什么。由于我仅添加到类中,为什么我不能与第二个DLL保持二进制兼容性?有什么办法解决吗?

2 个答案:

答案 0 :(得分:2)

我认为这是对正在发生的情况以及一些可能的解决方法的正确解释。

我组成了一个测试用例,再现了描述中的问题,然后使用OLEView从包含接口的新旧DLL中转储了IDL。

这是INewReport的旧(左)和新IDL的区别:

enter image description here

重要差异:

  • interface _INewReport的UUID已更改

  • 已添加称为INewReport___v0的typedef,它引用接口的原始 UUID

(我假设这也是问题中提到的代码所发生的事情。)

因此,现在在客户端项目中,bincomp DLL引用了原始接口UUID。但是该UUID仅与原始名称(INewReport___v0而不是INewReport)匹配。我认为这就是VB6认为bincomp不匹配的原因。


如何解决此问题?我无法在VB6中执行任何操作,使您无法将更新的接口DLL与客户端代码一起使用,而不必破坏客户端代码的bincomp。

(错误)选项可能只是更改客户端DLL以使用项目兼容性...但是在您所处的环境中,这可能会接受,也可能无法接受。除非所有使用者都重新编译,否则可能导致使用客户端DLL的程序中断。 (这可能会导致级联的bincomp损坏。)

一个更好但更复杂的选项是在IDL本身中定义接口,使用MIDL编译器生成typelib(TLB文件),然后直接引用该接口。然后,您将可以完全控制接口的命名等。您可以使用从OLEView生成的IDL作为起点。

第二个选项假定接口类实际上只是一个接口,并且其中没有功能代码。


这是我设置案例以重现此事的方式:

步骤1。原始接口定义-名为INewReport的类设置为二进制兼容:

Sub ProcA()    
End Sub    

Sub ProcB()    
End Sub

步骤2。创建一个测试客户端DLL,它实现INewReport,并且也设置为二进制兼容:

Implements INewReport    

Sub INewReport_ProcA()    
End Sub

Sub INewReport_ProcB()    
End Sub

第3步:将ProcC添加到INewReport并重新编译(它还会注册新构建的DLL):

(以上代码,加号:)

Sub ProcC()    
End Sub    

第4步:尝试运行或编译测试客户端DLL-立即获得OP的错误。无需更改任何引用或任何内容。

答案 1 :(得分:1)

我能够使用类似于DaveInCaz的代码来重新创建您的问题。我尝试了很多方法来修复它,可能是重复您已经尝试过的事情。我提出了一个可能的假设,说明为什么会这样。它不能解决问题,但可能会带来一些其他启示。

引用This doc page

  

为确保兼容性,Visual Basic对您对默认接口所做的更改施加了某些限制。 Visual Basic允许您添加新的类,并通过添加属性和方法来增强任何现有类的默认接口。删除类,属性或方法,或更改现有属性或方法的参数,将导致Visual Basic发出不兼容警告。

另一句话:

  

为确保与多个接口的兼容性必须遵循的ActiveX规则很简单:一旦使用了接口,就永远不能更改。标准接口的接口ID由定义接口的类型库固定。

因此,这是一个假设。第一个引号提到 default 接口,这表明可能无法以任何方式更改自定义接口。第二个引号也暗示了这一点。您可以更改接口类,因为实际上是在更改其默认接口。但是,当您尝试以实物方式更改实现类以反映接口中的更改时,实现参考指向的接口的旧版本已不再存在。当然,错误消息根本不会暗示这一点,因为它似乎是基于您没有尝试实现该接口的想法。

我还不能证明这一点,但是从DaveInCaz的答案来看,UUID已更改的事实似乎可以证明这一点。