confusion over COM interface layout

Started by
6 comments, last by ironfroggy 20 years, 2 months ago
Few questions about how a COM interface is laid out in memory: 1) Is there a vtable per object or per component? 2) Do the interfaces have to necessarily appear in order? that is, could QueryInterface return, for whatever reason, the interface of another object? 3) Is there a ''this'' pointer passed as the first argument to a COM objects'' methods? If so, what is it supposed to point at, if COM objects technically have no state?
(http://www.ironfroggy.com/)(http://www.ironfroggy.com/pinch)
Advertisement
I''ll take a stab at your questions. If my answers are incorrect, at least I''ve bumped your post.

1. vtables are defined per component, instanced for the first object and referenced for subsequent objects. A COM interface is basically a pointer to a vtable and a vtable is a struct of function pointers.

2. QueryInterface could return a different interface of the same object. For example, to move from the IUnknown interface to a more involved interface of the object (or from a more involved to a lesser). You can''t arbitrarily jump from one interface to another. They have to be related in some way.

3. Yes. Passing "this" is explicit in C, but implicit in C++. The "this" passed to methods is a pointer to the interface, which in turn is a pointer to the vtable for the interface. Take a close look at the core com header files - ole.h, ole2.h, oleauto.h, unknwn.h, oaidl.h, objbase.h, objidl.h etc - and pay close attention to the straight C portions. They will typically be marked "C style interface". You might need to track down a few pre-processor macros to fully make sense of things.

A couple of "old school" COM articles that I''ve found useful regarding COM memory layout are the "COM Cookbook" and the "Universal Delegator" (and Part 2).
"I thought what I'd do was, I'd pretend I was one of those deaf-mutes." - the Laughing Man
1) Technically, this is implementation defined. For a COM interface developed in C++ or VB, the vtable is almost always embedded in static memory and therefore there''s one copy per component. However, I''ve seen several C COM interfaces where there was one copy per object.

2) With COM aggregation, a QueryInterface call could technically return an interface on a different object. In practice, you shouldn''t try to tell the difference, and always treat the results of a QueryInterface call the same. For example, treating the reference count on each interface as distinct.

3) Many COM objects have state (actually I can''t think of a single one that doesn''t off the top of my head). While the only guarantee you have with a COM interface pointer is that it dereferences to a pointer to a vtable, additional data can be placed on either side of that pointer for state information.
What I meant about not having state is that access to this state is not defined as part of COM (its up to you where that state data goes) as it will almost always be used through calls to methods in the interfaces.

And the issue of the vtable is very much cleared up now, I just wasn''t sure if the pointer to the object was pointing to the first function pointer in the vtable, or to a pointer to the rest of the vtable, see?

You say some C implementations had a vtable per object? But, they still had a pointer to that vtable, yes?

Two further questions then:
1) Is the pointer to the object as the first argument of a COM method required, or just common practice? That is, could you have psuedo-static methods?
2) Is it assured that the vtable pointer in the object will remain constant from instansiation to destruction? That is, could I, for whatever odd reason, cause an object to use a different vtable at some point(s) in its lifetime? Of course, the vtables would implement the same interfaces, but perhaps I would wish to alter the overall functionality, such as switching between color depths, which each vtable using methods that handle a particular pixel format.

I say, "That is, ..." alot, don''t I?
(http://www.ironfroggy.com/)(http://www.ironfroggy.com/pinch)
Yes, they still had a pointer to the vtable.

I''m pretty sure the this pointer is required. Though, you can always just ignore the this pointer. Keep in mind you always need to have a live interface with a valid reference count in order to call a COM method, otherwise the results are undefined.

Switching vtable representations is just bad karma waiting to happen. I don''t know if it''s forbidden, but I wouldn''t rely on it behaving correctly. If you really want to do something like that, return a new interface when you switch pixel formats.
I could return a new interface when things change like that, but what if a lot of other objects were using this particular one? If I can change the vtable, then none of them have to worry about it. And, it wouldn''t change the interface at all, like I said. It would only be an undefined action, i think, if someone had grabbed the function pointer from the old vtable and was using that, which might be undefined by itself anyway.
(http://www.ironfroggy.com/)(http://www.ironfroggy.com/pinch)
To change a vtable is just a call for problems, specially if you interact between different languages (c, c++, vb, vba)
Thinking more on it, you can actually do internally and be yourself on the safe side, just add a level of indirection inside your components.

-Mat
Consult the "Universal Delegator" link(s) regarding changing vtables.
"I thought what I'd do was, I'd pretend I was one of those deaf-mutes." - the Laughing Man

This topic is closed to new replies.

Advertisement