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