为什么 COM 接口 return 相同调用方法的不同值?

Why does COM interface return different values for same invoking method?

当我在一个 COM 接口上调用一个 returns 另一个接口的方法时,每次 punkVal 都不一样。

然而,如果我使用旧的 punkVal 来调用该接口方法,它也能正常工作。似乎正在创建很多不必要的对象(或者可能是指向对象的指针),但我需要某种方式来确定返回的接口是否是唯一的。我所知道的是我调用的是返回一个接口(punkVal)并且每个实例的值都不同。该值指向的值始终相同,但我认为这是因为它指向 vtable 或其他东西,似乎不是可靠的检查。那,甚至看似完全不同的接口,其实都是同一个接口。

要明确:

someCOMInterface foo();

我在 foo 上调用 invoke 并期望 punkVal 是 someCOMInterface,稍后我必须查询它以使用 invoke 调用它的方法。但是每次我调用第一个调用时,我都会得到一个不同的 someCOMInterface("same" 但 "different" 因为调用返回的值)。

这并不少见。由多次调用同一方法得到的接口指针 return 是否 return 是同一个指针完全取决于 COM 库的开发人员。

可能 returned 不同指针的原因之一是特定 COM 库中使用的核心对象模型可能不是 COM。例如,我使用 shared_ptr 之类的东西在 C++ 中编写了对象模型,这可以说为 C++ 客户端生成了更好的对象模型。但是当我公开我的 C++ 对象模型以实现互操作性时(或者更一般地说,将其公开为 DLL),COM 通常是更好的选择。由于保持复杂的分层对象模型与一组包装器同步 类 可能很困难,因此包装器对象可能只是临时的——根据需要创建并在客户不再使用它们时销毁。

在这些情况下,客户端可能仍然需要知道对象是 "equal" -- 可以考虑包装同一内部对象的两个不同对象 "equal." 要确定这一点,Microsoft 定义IObjectEquality interface. This interface may be implemented by COM wrapper classes so that a client can explicitly check if two non-equal pointers are conceptually "equal" objects. The objects you're using may or may not implement this interface. This blog post 显示了使用此接口确定对象相等性的完整示例。

如果 IObjectEquality 没有实现,则由 COM 对象的开发人员提供一些方法来做出这样的决定,通常是提供某种 NameID 或其他标识 属性。例如,Excel 的 Application.Range property will return different pointers from subsequent calls with the same arguments. To determine if two ranges are equal, you can use the Range.Address 方法获取该范围的 "identifier",然后比较这些标识符。