Skip to content

rumbu13/windows-d

Repository files navigation

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.

Demo image

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 corresponding deprecated attribute. Guid keeps the same semantics as explained above.
  • NativeTypedef is used to decide where struct 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 a const 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)]

Similar projects: