Awesome
The D Windows SDK projection
Bindings of Windows SDK in D language based on metadata files generated by Win32 Metadata Project
Usage
Build the executable as needed and run it to generate source code files containing bindings for the Windows SDK. Latest run result ca be found here
D:\git\windows-d\bin>wind -h
Usage:
wind --meta <filename> --core <filename>
wind --meta <filename> --core <filename> --out <dir> --ignore <filename> --replace <filename>
Windows bindings generator for D
-m --meta Required: winmd file to process
-o --out output directory (defaults to 'out')
-i --ignore namespaces to ignore
-r --replace namespaces to replace
-d --docs generate documentation
-c --core Required: core.d file to be copied
-h --help This help information.
Example:
wind --meta .\meta\Windows.Win32.winmd --core .\cfg\core.d --out out --ignore .\cfg\ignore.cfg --replace .\cfg\replace.cfg --docs .\ext\win.sdk
Building
Build and run were tested on Windows, but the generator code is not platform dependent, it should work also on Linux. A dub.json
file is provided for convenience, but the application was compiled and tested only in Visual Studio using the corresponding solution file wind.sln
. Linux testers are welcome.
Features
Documentation
All functions, interfaces, enums and user defined types have descriptions extracted from the official Windows SDK documentation.
Code formatting
Lines have a maximum length of 120 characters. You can override this setting by changing the constant maxLineWidth = 120
. Function declarations are aligned to the width of the result type having a hard limit set in the constant maxReturnTypeAlignment = 8
. Struct members are also aligned to the width of the type having a hard limit that you can set in the constant maxFieldAlignment = 20
. Function parameters are also aligned to open paranthesis starting the parameter list.
struct CQPAGE
{
uint cbStruct;
uint dwFlags;
LPCQPAGEPROC pPageProc;
HINSTANCE hInstance;
int idPageName;
int idPageTemplate;
DLGPROC pDlgProc;
LPARAM lParam;
}
interface IServerSecurity : IUnknown
{
HRESULT QueryBlanket(uint* pAuthnSvc, uint* pAuthzSvc, ushort** pServerPrincName, uint* pAuthnLevel,
uint* pImpLevel, void** pPrivs, uint* pCapabilities);
HRESULT ImpersonateClient();
HRESULT RevertToSelf();
BOOL IsImpersonating();
}
Selective imports
Based on the dependency graph, imports between modules are limited to the types which are really used. All imports are public since there is no implementation of functions, only declarations.
module windows.componentservices;
public import windows.core;
public import windows.automation : BSTR, IDispatch, SAFEARRAY, VARIANT;
public import windows.com : APTTYPE, EOC_ChangeType, HRESULT, IClassFactory, IMoniker, IUnknown;
public import windows.systemservices : BOOL, HANDLE;
public import windows.winsock : BLOB;
public import windows.windowsprogramming : FILETIME;
Constant grouping
In the metadata files, constants are listed globally, the application tries to find a common pattern and group them accordingly. You can control this behaviour using the constant minSetTreshold = 0.4
representing the proportion of common characters.
enum : int
{
HH_TAB_INDEX = 0x00000001,
HH_TAB_SEARCH = 0x00000002,
HH_TAB_FAVORITES = 0x00000003,
HH_TAB_HISTORY = 0x00000004,
HH_TAB_AUTHOR = 0x00000005,
HH_TAB_CUSTOM_FIRST = 0x0000000b,
HH_TAB_CUSTOM_LAST = 0x00000013,
}
enum : int
{
HHACT_TAB_INDEX = 0x00000001,
HHACT_TAB_SEARCH = 0x00000002,
HHACT_TAB_HISTORY = 0x00000003,
HHACT_TAB_FAVORITES = 0x00000004,
}
Design
Strongly typed handles
In the metadata, most of the HANDLE
types are strongly typed as a struct
with a single member, forcing the use of that struct as a parameter for various functions. Also, these structs are decorated with a special attribute called RAIIFree
that you can use to auto-dispose the handle.
@RAIIFree!DeleteObject
struct HBITMAP { ... }
You will usually write the following code:
HBITMAP bitmap = CreateBitmap(128, 128, 1, 32, null);
//use bitmap
DeleteObject(bitmap)
Now you can take advantage of this attribute, by calling autofree
.
auto bitmap = CreateBitmap(128, 128, 1, 32, null).autoFree;
//use bitmap
//no need to call DeleteObject, it is called automatically when ```bitmap``` will go out of scope
GUID decorating
Interfaces and several structs are decorated with GUID attributes. The old IID_
constants from Windows headers are missing, therefore the generator will create them based on the name of each decorated item. The template doing this mapping (GUIDOF
) can be found in the file core.d
. Conventionally, every COM interface has an associated IID_
guid, any other type having an associated CLSID_
guid.
@GUID("8BA5FB08-5195-40E2-AC58-0D989C3A0102")
interface ID3DBlob : IUnknown
{
void* GetBufferPointer();
size_t GetBufferSize();
}
@GUID("7B40792D-05FF-44C4-9058-F440C71F17D4")
struct CTraceRelogger;
const GUID IID_ID3DBlob = GUIDOF!ID3DBlob;
const GUID CLSID_CTraceRelogger = GUIDOF!CTraceRelogger;
Library decorating
All functions are decorated with a @DllImport
attribute stating the corresponding library file where the function can be found. This can be useful later for generating .lib files or for loading function using dynamic bindings.
@DllImport("d3d12")
HRESULT D3D12EnableExperimentalFeatures(uint NumFeatures, char* pIIDs, char* pConfigurationStructs,
char* pConfigurationStructSizes);
Renaming
Every type, method or field identifier is renamed by adding an underscore at the end if there is a conflict with any of existing D keywords.
HRESULT GetVersion(ulong* version_);
Other attributes
Not all attributes found in the metadata have a direct translation in D language.
Obsolete
is translated in a correspondingdeprecated
attribute.Guid
keeps the same semantics as explained above.NativeTypedef
is used to decide wherestruct
is in facta a strong typed handles.UnmanagedFunctionPointer
is used to decide what calling convention is used for callback functions.Const
attribute is translated as aconst
qualifier for all fields or all parameters.- The following attributes are ignored:
NativeArrayInfo
,ComOutPtr
,RetVal
,NullNullTerminated
,NotNullTerminated
. Any suggestion about how to take advantage of them is appreciated.
enum : int
{
OCR_IBEAM = 0x00007f01,
OCR_WAIT = 0x00007f02,
OCR_CROSS = 0x00007f03,
OCR_UP = 0x00007f04,
deprecated("use OCR_SIZEALL") //this was marked as [Obsolete("use OCR_SIZEALL")]
OCR_SIZE = 0x00007f80,
deprecated("use OCR_NORMAL") //this was marked as [Obsolete("use OCR_NORMAL")]
OCR_ICON = 0x00007f81,
OCR_SIZENWSE = 0x00007f82,
OCR_SIZENESW = 0x00007f83,
OCR_SIZEWE = 0x00007f84,
OCR_SIZENS = 0x00007f85,
OCR_SIZEALL = 0x00007f86,
}
alias FNAPONOTIFICATIONCALLBACK = extern(Windows) HRESULT function(APO_REG_PROPERTIES* pProperties, void* pvRefData);
//this was marked as [UnmanagedFunctionPointer(CallingConvention.Winapi)]
struct AudioFXExtensionParams
{
LPARAM AddPageParam;
const(wchar)* pwstrEndpointID;
IPropertyStore pFxProperties;
}
//pwstrEndpointID was marked with [Const(true)]
HRESULT GetInterfaceFromGlobal(uint dwCookie, const(GUID)* riid, void** ppv);
//riid was marked with [Const(true)]