Thread overview
Wrong vtable for COM interfaces that don't inherit IUnknown
Jul 15, 2019
KytoDragon
Jul 16, 2019
Nicholas Wilson
Jul 16, 2019
evilrat
Jul 16, 2019
KytoDragon
Jul 21, 2019
Kagamin
Jul 21, 2019
rikki cattermole
Jul 21, 2019
Kagamin
July 15, 2019
I am currently trying to write a XAudio2 backend and have come across the problem, that some of the interfaces for XAudio2's COM objects seem to be missing the first entry in their vtable. After reading the iterface article in the spec (https://dlang.org/spec/interface.html#com-interfaces) it seems that only interfaces inheriting from core.stdc.windows.com.IUnknown (or any interface named "IUnknown") get the COM interface layout instead of the D layout.

What can I do to get the COM layout on interfaces that don't inherit IUnknown?
Examples: IXAudio2Voice or any of the IXAudio2*Callback interfaces. I have already declared everything extern(Windows), but that does not fix it.
July 16, 2019
On Monday, 15 July 2019 at 22:01:25 UTC, KytoDragon wrote:
> I am currently trying to write a XAudio2 backend and have come across the problem, that some of the interfaces for XAudio2's COM objects seem to be missing the first entry in their vtable. After reading the iterface article in the spec (https://dlang.org/spec/interface.html#com-interfaces) it seems that only interfaces inheriting from core.stdc.windows.com.IUnknown (or any interface named "IUnknown") get the COM interface layout instead of the D layout.
>
> What can I do to get the COM layout on interfaces that don't inherit IUnknown?
> Examples: IXAudio2Voice or any of the IXAudio2*Callback interfaces. I have already declared everything extern(Windows), but that does not fix it.

From memory COM interfaces are really just `extern(C++) interface`s, so

extern(C++) interface IXAudio2Voice
{
    //methods...
}

should do the trick


July 16, 2019
On Monday, 15 July 2019 at 22:01:25 UTC, KytoDragon wrote:
> I am currently trying to write a XAudio2 backend and have come across the problem, that some of the interfaces for XAudio2's COM objects seem to be missing the first entry in their vtable. After reading the iterface article in the spec (https://dlang.org/spec/interface.html#com-interfaces) it seems that only interfaces inheriting from core.stdc.windows.com.IUnknown (or any interface named "IUnknown") get the COM interface layout instead of the D layout.
>
> What can I do to get the COM layout on interfaces that don't inherit IUnknown?
> Examples: IXAudio2Voice or any of the IXAudio2*Callback interfaces. I have already declared everything extern(Windows), but that does not fix it.

As you can see it is by design. IUnknown has different vtbl[] comparing to regular D classes/interfaces. If it works with declaring your own empty IUnknown use it, also you can try extern(C++) which does similar thing to vtable, it might even work!

Another option is to craft your own "vtable" with structs, but I'm not going into details about that, you can always google how to do it in C and adapt.

And finally you can swap vtable for object instances at runtime, this however is the most complicated and error prone solution, I for example doesn't fully understand D rules for vtable constructing, esp. confusing is that interface entry notice, so anything non trivial (such as class inheriting from class w/multiple interfaces) is beyond me. Expect heavy AV storm.


Also from what I see MS done this intentionally, means they either no longer loves COM or there was some other good reason.


Oh and let me put this here...
Have you seen this? It even has very simple xaudio example.
https://code.dlang.org/packages/directx-d
July 16, 2019
On Tuesday, 16 July 2019 at 01:38:49 UTC, evilrat wrote:
> As you can see it is by design. IUnknown has different vtbl[] comparing to regular D classes/interfaces. If it works with declaring your own empty IUnknown use it, also you can try extern(C++) which does similar thing to vtable, it might even work!
...
> Oh and let me put this here...
> Have you seen this? It even has very simple xaudio example.
> https://code.dlang.org/packages/directx-d

Yes, i found that after posting. Declaring your interface extern(C++) and the methods in the interface extern(Windows) seems to do the trick. I hoped there would be a more elegant solution than to annotate each interface, but oh well.
Thanks anyway!
July 21, 2019
On Tuesday, 16 July 2019 at 01:38:49 UTC, evilrat wrote:
> Also from what I see MS done this intentionally, means they either no longer loves COM or there was some other good reason.

Primary consumer of COM interfaces is Visual Basic. It was really only Bill Gates who loved Basic, he wrote a Basic interpreter in 1975 and created Microsoft as a business that sold Basic interpreters. As gamedev was locked in C++, there was no real use case for COM there, so MS probably does the expected thing and goes with straight C++.
July 21, 2019
On 21/07/2019 5:44 PM, Kagamin wrote:
> On Tuesday, 16 July 2019 at 01:38:49 UTC, evilrat wrote:
>> Also from what I see MS done this intentionally, means they either no longer loves COM or there was some other good reason.
> 
> Primary consumer of COM interfaces is Visual Basic. It was really only Bill Gates who loved Basic, he wrote a Basic interpreter in 1975 and created Microsoft as a business that sold Basic interpreters. As gamedev was locked in C++, there was no real use case for COM there, so MS probably does the expected thing and goes with straight C++.

I suspect both of you are wrong in this regard.

"No other XAudio2 objects are reference-counted; their lifetimes are explicitly controlled using create and destroy calls, and are bounded by the lifetime of the XAudio2 object that owns them."

https://docs.microsoft.com/en-us/windows/win32/api/xaudio2/nn-xaudio2-ixaudio2

COM is used heavily in WinAPI since about Vista. Pretty much all new functionality has been exposed by it and NOT extern(Windows) functions which was the standard during up to about XP (for example notification icons would today be COM based but isn't).

E.g. jump lists https://docs.microsoft.com/en-us/windows/win32/api/shobjidl_core/nn-shobjidl_core-icustomdestinationlist

Windows isn't the only one with a solution like COM.
Linux has D-Bus which underpins most newer Desktop Environments.
You can do everything from shutdown, log out and even send notification messages via it.
July 21, 2019
On Sunday, 21 July 2019 at 07:04:00 UTC, rikki cattermole wrote:
> COM is used heavily in WinAPI since about Vista. Pretty much all new functionality has been exposed by it and NOT extern(Windows) functions which was the standard during up to about XP (for example notification icons would today be COM based but isn't).
>
> E.g. jump lists https://docs.microsoft.com/en-us/windows/win32/api/shobjidl_core/nn-shobjidl_core-icustomdestinationlist

Shell object library? It shipped with Internet Explorer 4 and was installable on windows 95. Shell (explorer) is not really winapi, it's more or less a normal userland application that provides integration, like an RPC server, in this way it can be similar to d-bus, but it's difficult to say, because the library abstracts whether it works in process or out of process, most (older) shell objects work in process and simply provide shell logic like moving files to trash bin and creating shortcuts.