core.sys.windows.com.ComObject apparently has wrongly laid out Vtable
Walter Bright
newshound2 at digitalmars.com
Thu Mar 21 16:10:25 UTC 2024
On 3/21/2024 7:30 AM, Carl Sturtivant wrote:
> On Thursday, 21 March 2024 at 03:38:18 UTC, Walter Bright wrote:
>> A com object is an interface, not a class. All com objects must derive from
>> core.sys.windows.unknwn.IUknown, or from an interface that derives from IUnknown.
>>
>> IUnknown uses the extern (Windows) calling convention.
>>
>> For com objects, slot 0 in the vtbl[] is for QueryInterface(), not the classinfo.
>
> It's nice that the D language itself makes this happen for
> `core.sys.windows.unknwn.IUnknown` specially so as to make writing a COM client
> using a class possible and having it pass on its extern(Windows) calling
> convention is nice too.
>
> As you say, all COM objects must inherit from this --- otherwise they don't get
> the twin benefits of extern(Windows) calling and a COM compatible vtbl[] for
> their IUnknown interface.
>
> Can we get those benefits out here without `core.sys.windows.unknwn.IUnknown` by
> definining a class extern(C++) to get a COM compatible vtbl[] and then
> qualifying each of its methods as extern(Windows) to get COM compatible calling,
> and writing our methods in the correct COM order, starting with QueryInterface,
> AddRef, Release, and relying on D to place the methods in the vtbl[] in that order?
No, because the vtbl[] layout is different.
> (Of course, this won't then bless the descendants of such an interface or class,
> the way the descendents of `core.sys.windows.unknwn.IUnknown` are blessed by a
> special dispensation in the D language definition, but still. It would be very
> nice if we could so bless an interface or class ourselves with `extern(COM)`,
> fixing the vtbl[], calling convention, and method ordering in the vtable rules,
> for self and any descendant.)
>
> I ask if we can get these benefits ourselves as above because there's an
> external world difficulty using `core.sys.windows.unknwn.IUnknown` with the rest
> of Windows programming outside of just using `core.sys.windows.windows` and
> suchlike.
>
> `core.sys.windows.unknwn.IUnknown` forces the definition of
> `core.sys.windows.basetyps.GUID` into any COM code written using it because the
> first parameter of `core.sys.windows.unknwn.IUnknown.QueryInterface` is defined
> to be of type `IID*` and `IID` is defined to be `const(GUID)`, all in
> `core.sys.windows.basetyps`.
>
> Now if ImportC is used to bring in Windows COM related headers so as to use the
> wide collection COM machinery there, a binary-identical GUID type is defined in
> `guidef.h` and used throughout. Inheriting from
> `core.sys.windows.unknwn.IUnknown` to make COM objects of type that interface
> means that QueryInterface will have the wrong type for its first parameter to
> work with all of Windows COM machinery. Working around this is awkward.
You can invent your own COM-like system in D by using interfaces, but they won't
work with Windows COM code.
More information about the Digitalmars-d
mailing list