使用C++Builder实现COM对象的后期绑定

5
我们正在从C++Builder 2010应用程序与一些第三方COM对象进行接口交互。
目前,我们导入类型库并生成组件包装器,然后可以相对自然地进行方法调用和访问属性。
object->myProperty = 42;
object->doSomething(666);

然而,由于COM对象接口的更改(仍在扩展和开发中),导致我们自己的应用程序失败,因为一些方法GUID似乎会失效 - 即使接口的唯一更改是添加了一个新方法。建议使用Late Binding来解决这个问题。我认为这需要更改我们的代码,就像这样:链接
object.OlePropertySet("myProperty", 42);
object.OlePrcedure("doSomething", 666);

很显然这种写法读起来和写起来都很痛苦,所以我们需要写包装类。

是否有办法在导入类型库时自动生成延迟绑定的包装类?如果可以,它们是否足够聪明,只在对象创建时进行文本绑定一次,而不是在每个方法调用时都进行?

2个回答

3
当您为支持晚期绑定(即实现IDispatch接口)的COM对象导入TypeLibrary时,导入程序可以为静态绑定和晚期绑定分别生成包装器类(而不是组件)。
向现有接口添加新方法不应使您的代码无效。 方法没有GUID。 但是,对于基于IDispatch的接口,其方法确实与之关联的DISPID值,并且这些DISPID值可以从一个版本更改到另一个版本。 尽管任何合格的COM开发人员一旦确定接口定义就不应该这样做。

1
谢谢,请问你可以给我指一个如何使用(或选择)后期绑定类的例子吗?目前我正在使用<libfile>_OCX.hpp头文件中的T<classname>对象。 - Roddy
我认为C++和C++Builder缺少Delphi所具备的复杂后期绑定功能,这是Delphi编译器的特色。(声明variant,调用CreateOleObject,调用方法。)相反,您必须通过艰苦的方式实现它。在C++中查找“OLE Automation”示例,技术和编码风格是一样的。 - Warren P
1
C++Builder中的VariantOleVariant类支持类似于Delphi编译器本地支持的后期绑定操作,就像Roddy所展示的那样,即在Delphi中object.myProperty := 42;变成了在C++中的object.OlePropertySet("myProperty", 42);,在Delphi中的object.doSomething(666);变成了在C++中的object.OleProcedure("doSomething", 666);等。 - Remy Lebeau
@RemyLebeau - 添加了一个答案,使用 IxxxDisp 包装器,提供 DISPID-based 绑定。 - Roddy

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的包装器,即使对象的vtable布局发生了变化,方法也将按照它们的DISPIDs进行分派。我认为这些类还提供了一种按函数名称而不是DISPID进行分派的方法,但尚未确认其详细信息。

注意:接口一旦发布,就应该被“冻结”,即给定的IID对应于给定的vtable,没有其他情况。因此,客户端使用vtable绑定是安全的。如果您想添加新成员,则应从该接口派生。 - M.M
1
此外(至少对于DAX而言),f.myMethod使用硬编码的DISPID和IDispatch::Invoke;而f->myMethod则使用vtable。 - M.M
@MattMcNabb 感谢你提供的DAX消息。BCB2010似乎没有使用这个,虽然据我所知。而且,在理想的世界中,界面应该是冻结的。可惜我似乎并不在其中。 - Roddy

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接