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