5

我们正在与来自 C++Builder 2010 应用程序的一些第 3 方 COM 对象进行交互。

目前我们导入类型库并生成组件包装器,然后能够以相当自然的方式进行方法调用和访问属性。

object->myProperty = 42;
object->doSomething(666);

然而,我们已经被 COM 对象的接口(仍在扩展和开发)的变化所困扰,导致我们自己的应用程序失败,因为某些方法 GUID 似乎变得无效 - 即使接口的唯一变化是添加一种新方法)。

已建议将后期绑定作为解决此问题的一种方式。我认为这需要像这样更改我们的代码:

object.OlePropertySet("myProperty", 42);
object.OlePrcedure("doSomething", 666);

显然,这读和写起来很痛苦,所以我们不得不编写包装类。

当我们导入类型库时,有什么方法可以自动生成后期绑定包装器?而且,如果是这样,它们是否足够聪明,只在创建对象时进行一次文本绑定,而不是在每个单独的方法调用上?

4

2 回答 2

3

当您为支持后期绑定(当它实现接口时)的 COM 对象导入 TypeLibrary 时,导入IDispatch器可以为静态绑定和后期绑定生成单独的包装类(而不是组件)。

向现有接口添加新方法不应使您的代码无效。方法没有 GUID。但是,对于IDispatch基于 - 的接口,它的方法确实具有DISPID与之关联的值,并且这些DISPID值可以从一个版本更改为另一个版本。尽管一旦锁定了接口定义,任何受人尊敬的 COM 开发人员都不应该这样做。

于 2012-07-27T18:44:30.567 回答
0

在深入研究了 TLIBIMP 生成的代码和标头之后,这变得相当容易。

如果您的类型库有一个类Foo,那么在导入类型库后,您通常会使用自动生成的智能指针类IFooPtr

{
  IFooPtr f;
  ...
  f->myMethod(1,2);
}

您应该注意,此时绑定是静态的 - 也就是说,它们不仅取决于对象的 GUID 和方法的 DISPID,还取决于 DLL 中 VTable 的确切布局。任何影响 vtable 的更改 - 例如,向基类添加额外Foo的方法将导致方法调用失败。

要使用动态绑定,您可以使用IFooDisp类而不是IFooPtr. 同样,这些是智能包装器,自动处理对象生命周期。请注意,对于这些类,您应该使用.运算符来访问方法,而不是间接->运算符。使用间接运算符将调用该方法,但通过静态绑定。

{
  IFooDisp f;
  ...
  f.myMethod(1,2);
}

通过使用这些IDispatch基于包装器,方法将由它们的 DISPID 分派,即使对象 vtable 布局已更改。我认为这些类还提供了一种通过函数名而不是 DISPID 进行调度的方法,但尚未确认其细节。

于 2013-12-17T23:18:28.617 回答