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.