combindings and directxbindings

Ethan gooberman at gmail.com
Sun Sep 6 18:14:25 UTC 2020


https://github.com/GooberMan/combindings
https://github.com/GooberMan/directxbindings

I needed some DirectX 12 bindings. Autogeneration was out of the 
question. The .idl files Microsoft uses internally is full of 
plain C++ code that is inserted in to headers without additional 
parsing, and DirectX is basically useless without those #defines 
and function definitions. So in between compile times elsewhere, 
I hand converted the necessary headers to D modules.

Then me being me, I wanted to go one step further. Why should it 
just be a direct translation? Why not have some convenience 
methods added?

So now there's two libraries.

combindings - A thin layer that defines COM compatible UDAs and 
autogenerates some convenience features
directxbindings - Little more than direct hand-done translations 
of DirectX headers to D

These will be updated as I use them. And they're essentially 
mostly untested right now, I'm testing as I go.

They're also released under a Creative Commons 0 license. It 
seems to be the only really valid public domain license 
internationally; and these are COM bindings. There's no way I 
should be attributed on a random project just because you're 
using a very thin glue layer I wrote for something that should 
just plain exist as a D feature anyway (ie COM interface 
autogeneration).

COM Bindings aims for compatability first, and convenience 
second. The idea is that you should be able to copy/paste code 
from C++, replace the -> with . and off you go. That's not 
_entirely_ possible for one very good reason: the IID_PPV_ARGS 
macro. This expands to two symbols meant to be inserted in a 
function call in C++. If you want to do something similar in D, 
both templates and mixin templates are entirely unsuitable. You 
need to resort to string mixins. *UGLY* *UGLY* *UGLY* why even 
bother moving to D if you're going to be uglier than C++.

Next step then. We analyse function attributes. If we find a 
@_COM_Outptr_ or @_COM_Outptr_opt_ attribute in a function and 
the previous parameter is a REFIID, then sweet. We know what to 
do. For example, the following C++ code:

HRESULT result = D3D12CreateDevice(adapter, 
D3D_FEATURE_LEVEL_12_0, IID_PPV_ARGS(&device));

Can be translated to the following thanks to the wrapper stubs 
generated:

HRESULT result = D3D12CreateDevice(adapter, 
D3D_FEATURE_LEVEL_12_0, device);

And if you really really want, you can still just do a direct 
translation of equivalent C++ code:

HRESULT result = D3D12CreateDevice(adapter, 
D3D_FEATURE_LEVEL_12_0, &IID_IDirect3D12Device, 
cast(void**)&device);

Or try something that doesn't require linking to external 
variables:

HRESULT result = D3D12CreateDevice(adapter, 
D3D_FEATURE_LEVEL_12_0, device.IIDPtrOf, cast(void**)&device);

HRESULT result = D3D12CreateDevice(adapter, 
D3D_FEATURE_LEVEL_12_0, IIDPtrOf!IDirect3DDevice12, 
cast(void**)&device);

Likewise when you have functions where the output device is 
optional, you can just straight up template instantiate them:

HRESULT result = D3D12CreateDevice!IDirect3DDevice12(adapter, 
D3D_FEATURE_LEVEL_12_0 );


More information about the Digitalmars-d-announce mailing list