Skip to content

marlersoft/zigwin32gen

Repository files navigation

zigwin32gen

Generates Zig bindings for Win32 using https://github.com/marlersoft/win32json. If you just want to use the bindings, see https://github.com/marlersoft/zigwin32.

How to generate the Windows Zig bindings

Download zig, currently tested on version: 0.12.0-dev.2701+d18f52197

First, clone the zigwin32 repo from the root of this repository to provide a location for the generated files:

git clone https://github.com/marlersoft/zigwin32

Then run the following command to generate the latest bindings:

zig build

On the first run, running this command will provide an error message saying that the win32json dependency is missing, and will provide you with a git command to clone it and checkout the expected version.

Once the build task completes, you can view your generated code in the zigwin32 subrepository that you cloned earlier.

win32json vs C/C++ Win32 SDK

The win32metadata project from which win32json is generated does not expose the exact same interface as the classic C/C++ header files did. One thing I'd like is to support is to be able to take a Windows C/C++ example and port it to Zig without changing any names/types or the way it interfaces with the Windows API. To support this I'll need to:

  • Support a set of modules with the same structure as the Window headers. For example, importing the windows module should have all the same declarations as the windows.h header.
  • Generate structs with the same field names (hungarian notation)
  • Support code that can be compiled for either Ascii or Wide characters. Provide mappings like CreateFile to CreateFileA or CreateFileW based on this configuration.

For example, intead of DWORD or UINT32, I would generate u32. Instead of field names with hungarian notation, I would generate them with snake case. These would only be cosmetic changes, where it would look more natural to use the Windows API directly alongside other Zig APIs. The bigger advantage to this is not having to track all the different ways to declare the same type, for example, a developer having to know that DWORD, UINT32, ULONG, UINT are all the same as u32.

  • I may want to be able support different "views" into the api that change things like how to import the api. These extra views should not add to compile-time unless they are being used.
  • I may want to consider also generating wrapper APIs? It's clear that wrapping APIs should exist, but I'm not sure if this wrapping API should be created/maintained manually or autogenerated from the Windows API data.
  • I may want to make it possible to generate subsets of the complete API. One example of where this could be used it to generate bindings to be included in the standard library, where only a small portion of the complete API is required.

extra.txt

This file contains extra metadata, namely,

  • whether pointer types are "union pointers"
  • whether pointer types are "not null"

"Union Pointers" are pointers that in addition to actual pointer values also accept special reserved values that aren't actually pointers.

It's important for Zig to know when this is the case because Zig inserts runtime alignment checks when casting non-pointer values to pointers. To address this, anytime a pointer type is actually a "union pointer", we annotate that pointer type with align(1) to ellide this runtime alignment check. Note that the reason for using align(1) instead of a union type is because modifying a parameter type to be a union instead of a pointer can modify the ABI. See dotnet/coreclr#23974 (comment) for an example of this.

See Issue "CreateWindowEx lpClassName union": microsoft/win32metadata#623

We also add include extra information about which pointers are "not null". By default, all pointer types in the metadata are treated as being "optional" (i.e. ?*T). We can override this default by providing a "NotNull" modifier in extra.txt.

The "NotNull" modifier is a sequence of 0/1 flags. Each flag modifies a pointer in the type to be "non-optional". For example, consider the type ?*?*?*T. The integer value 0 would leave the type unmodified. The modifier 1 would modify the first pointer in the type to make it *?*?*T. The modifier 10 would modify the second pointer in the type to become ?**?*T. The integer value 111 would modify all 3 pointer types to become ***T.

About

Generates Complete Zig bindings for Win32. See https://github.com/marlersoft/zigwin32 for the bindings themselves.

Resources

Stars

Watchers

Forks

Releases

No releases published

Packages

No packages published