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