简体   繁体   中英

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

When I invoke a method on a COM interface that returns another interface, the punkVal is different each time.

Yet if I use the old punkVal's to invoke that interfaces methods, it too works. It seems like a lot of unnecessary objects(or probably pointers to objects) are being created but I need someway to determine if the returned interface is unique. All I know is that I invoke is returning an interface(punkVal) and the value is different every instance. The value pointed by that value is always the same, but I think it is because it points to the vtable or something, doesn't seem to be a reliable check. That, or even seemingly disparate interfaces are all actually the same interface.

To be clear:

someCOMInterface foo();

I call invoke on foo and expect punkVal to be someCOMInterface, which I must later on query to call it's methods using invoke. But each time I call the first invoke I get a different someCOMInterface(the "same" but "different" in that the value returned by invoke).

This isn't uncommon. It is entirely up to the developer of the COM library whether interface pointers returned from multiple calls to the same method will return the same pointer or not.

One of the reasons that different pointers may be returned is that the core object model used within a specific COM library may not be COM. I have, for example, written object models in C++ using things like shared_ptr , which arguably yields a better object model for C++ clients. But when I expose my C++ object model for interoperability (or, more generally, expose it as a DLL), COM is often a better choice. Since keeping an complex, hierarchical object model in sync with a set of wrapper classes can be difficult, wrapper objects may just be temporary -- created as necessary and destroyed whenever clients no longer use them.

In these circumstances, the client may still need to know that the objects are "equal" -- two different objects that wrap the same inner object can be considered "equal." To determine that, Microsoft defines the 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 shows a complete example of determining object equality using this interface.

If IObjectEquality is not implemented, it is up to the developer of the COM object to provide some means of making such a determination, usually by providing some sort of Name or ID or other identifying property. For example, Excel's 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 method to get an "identifier" of that range, and then compare those identifiers.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM