Here's the test of that extern(C++) ComObject.
import std.stdio;
import com = core.sys.windows.com;
import windows = core.sys.windows.windows;
import comdef;
pragma(lib,"onecore");
void main() {
//auto COMobject = new com.ComObject();
auto COMobject = new ComObject();
IUnknown* ip = cast(IUnknown*)COMobject;
writeln(COMobject.count);
writeln(" ip vtable: ", ip.lpVtbl);
auto vtable = COMobject.__vptr;
writeln("COMobject vtable: ", vtable);
writeln("ip &AddRef: ", &ip.lpVtbl.AddRef);
writeln("ip offset: ", cast(void*)&ip.lpVtbl.AddRef - cast(void*)ip.lpVtbl);
auto ipaddref = cast(void*)ip.lpVtbl.AddRef;
writeln(" ip AddRef: ", ipaddref);
auto addref = cast(void*)(&COMobject.AddRef).funcptr;
writeln("COMobject AddRef: ", addref);
writeln("COMobject AddRef : ip AddRef offset: ", addref - ipaddref);
COMobject.AddRef();
writeln(COMobject.count);
ip.lpVtbl.AddRef(ip);
writeln(COMobject.count);
}
Note that I cast COMobject (which is a new ComObject) directly to a IUnknown*. (Here IUnknown is the struct defined in comdef.c
just the way Windows defines it.) This code works! The result:
0
ip vtable: 7FF6AFEB0360
COMobject vtable: 7FF6AFEB0360
ip &AddRef: 7FF6AFEB0368
ip offset: 8
ip AddRef: 7FF6AFE31580
COMobject AddRef: 7FF6AFE31580
COMobject AddRef : ip AddRef offset: 0
1
2
This shows that the Vtable of the extern(C++) ComObject has COM interface layout. However, if I remove extern(C++)
from the definition of the new ComObject class, now this does NOT work. Result without extern(C++) is:
0
ip vtable: 7FF6C74D02B0
COMobject vtable: 7FF6C74D02B0
ip &AddRef: 7FF6C74D02B8
ip offset: 8
ip AddRef: 7FF6C74619E0
COMobject AddRef: 7FF6C7451580
COMobject AddRef : ip AddRef offset: -66656
1
1
This shows the Vtable of the ComObject does not have COM interface layout.