core.sys.windows.com.ComObject apparently has wrongly laid out Vtable

Carl Sturtivant sturtivant at gmail.com
Thu Mar 21 14:30:24 UTC 2024


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?

(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.




More information about the Digitalmars-d mailing list