Git Product home page Git Product logo

zigwin32gen's People

Contributors

fabioarnold avatar flaminator avatar kcbanner avatar leecannon avatar marler8997 avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar

zigwin32gen's Issues

_T function in ansi mode generates return type error.

The _T function found in /src/zig.zig#L17 gives back the following error when you use it when running the program in ansi mode:

.\win32\win32\zig.zig:17:75: error: expected type '*const [4:0]u8', found '[]const u8'

Ran into this when I was playing around trying to see if I could build my program run on Windows 2000(Found out it doesn't).

Some IUnknown pointers should be optional

I'm not sure if this is an issue with the metadata project or the interpretation into Zig types. If it's the former let me know and I will open an issue over there. ๐Ÿ™‚

The documentation for DirectSoundCreate and IDirectSound::CreateSoundBuffer says the following about their final LPUNKNOWN pUnkOuter parameters:

  • pUnkOuter
    Controlling unknown of the aggregate. Its value must be NULL.

However these parameters are not optional in the Zig interface. Is null a valid value for all LPUNKNOWNs or is this an omission in the metadata?

Support PackingSize > 1

A "PackingSize" of 0 is equivalent to an extern struct/union in Zig, and a PackingSize of 1 is equivalent to a packed struct/union in Zig. However, Zig doesn't have a way to modify a struct to emulate packing sizes larger than 1.

My current idea to support this, is when the packing size is greater than 1, I can use a packed struct, and then add padding between each field based on the size of the previous field, i.e.

// emulate PackingSize of 2
const S = packed struct {
    foo: T,
    _padding0_: PaddingFor(T, 2),
    bar: U,
    _padding1_: PaddingFor(U, 2),
};

// emulate PackingSize of 4
const S = packed struct {
    foo: T,
    _padding0_: PaddingFor(T, 4),
    bar: U,
    _padding1_: PaddingFor(U, 4),
};

examples/build.zig needs update

I am a zig noob so not entirely sure, but I believe this file needs to be updated for the new zig version in order to be able to build the examples properly

Additional metadata for pointer union types

This is a follow up to the discussion here: microsoft/win32metadata#623

The issue is that some win32 pointer parameters accept more than just pointers, but Zig verifies pointer alignment which prevents these non-pointer values from being passed. For example, calling CreateWindowEx with the return value of RegisterClass for lpClassName will trigger a pointer alignment issue when performing an alignCast from ATOM to LPCSTR.

It was also discussed that changing these pointer parameters to a union type can break the ABI since some ABI's treat pointers and structure types differently, even if the structure itself is made up of a single pointer value.

So given these constraints, the solution I came up with for Zig is to maintain additional metadata that indicates which of these pointer parameters or fields can accept other non-pointer values and add align(1) to those pointer types. If another projection would also like this additional metadata, then this extra data could be upstreamed and turned into a new attribute in the Microsoft supplied metadata. Note that since this is a possibility, I should make the implementation as similar to an attribute as I can.

Metadata for strings optionally requiring zero termination

The issue is that some win32 string pointer parameters accept strings that are optionally zero terminated. The associated length parameter determines the length (e.g. TextOut()) or in some instances (e.g. DrawTextEx()) a length parameter of -1 can allow the string to be zero terminated.

There is "NullNullTerm":false in the JSON metadata that appears to indicate where the parameter should be [*] rather than the current [0:*].

Sharing code with `std`

The goal is to be able to share type definitions between the std and win32 packages. The long-term plan is to update this tool to be able to generate the bindings that will be included in std. This should be as simple as keeping a list of constants/types/functions that would be set apart for inclusion in std. At the same type, all references to these types would be updated to pull them from "std".

In order to support updates to win32 that aren't necessarily in sync with std, I'll also want a way to switch between referencing std and referencing the std win32 types generated by this project. I'm not sure the best way to do this yet. Maybe std should allow this package to be overriden? I could reserve stdwin32" as a special package name that std` imports to get all the win32 types.

DETAILS

  1. I think I'll define what std needs as a set of functions, then perform a first pass on the metadata to determine what types/constants it needs.
  2. As I'm generating code, if something is moved to std, then an alias will remain in the api it appears in. This means that inter-api references will still work.
  3. I'll start by defining a set of constants/types/functions manually to move, then get the code to be able to move those to another module, I'll start with a single win32/std.zig module for now I think.

How to override win32 bindings in std

The current idea is to allow an application to override the win32 bindings in std with the following line in the root module:

// Use the version of std code in win32
pub const stdwin32 = @import("win32").std;

zigwin32gen will generate code meant to be included in std. That being said, a user may want to use the currently generated version of this std code rather than the one shipped with their compiler. I think I can do this by checking for a pub symbol named stdwin32 in the root module.

In these examples, assume that the generated code meant for std is deployed to std/os/windows/win32.zig.

In std/os/windows.zig

const root = @import("root");
pub const win32 = if (@hasDecl(root, "stdwin32")) root.stdwin32 else @import("windows/win32.zig");

Overrides?

daurnimator asked if zigwin32 had the ability to override types. He suggested the root module could do something like this:

pub const zigwin32_config = struct {
    pub const overrides = struct {
        pub const SOME_STRUCT = struct{....}
    };
};

To support this, whenever I generate a type, instead of this:

pub const SOME_STRUCT = struct {
    //...
};

I could do something like this:

pub const SOME_STRUCT = if (getOverride("SOME_STRUCT")) |o| o else struct {
    //...
};

Where getOverride would look something like:

pub fn getOverride(comptime sym: []const u8) ?type {
    const root = @import("root");
    if (@hasDecl(root, "zigwin32_config")) {
        if (@hasDecl(root.zigwin32_config, "override")) {
            if (@hasDecl(root.zigwin32_config.override, sym)) {
                return @field(root.zigwin32_config.override, sym);
            }
        }
    }
    return null;
}

Note that this mechanism could be leveraged to help with a solution to the std interop problem.

Should flags be represented as enums?

Regarding this TODO:

try writer.line("// TODO: This Enum is marked as [Flags], what do I do with this?");

Is there a big benefit to representing these values as non-exhaustive enums? My impression is that the common case is combining multiple bitmask values together which is awkward with the current setup. For example:

const std = @import("std");
const win32 = @import("win32").everything;

const class = std.mem.zeroInit(win32.WNDCLASSEXA, .{
    .style = @intToEnum(win32.WNDCLASS_STYLES, @enumToInt(win32.CS_HREDRAW) | @enumToInt(win32.CS_VREDRAW) | @enumToInt(win32.CS_OWNDC)),
});

support new for loops

for (slice) |item, i| -> for (slice, 0..) |item, i|

change as of 0.11.0-dev.1681+0bb178bbb

Flexible Array Member convenience method

Win32 will sometimes use a "flexible array member" to copy data to/from the application. The GetInterfaceInfo function is an example:

https://docs.microsoft.com/en-us/windows/win32/api/iphlpapi/nf-iphlpapi-getinterfaceinfo

//...

    dwRetVal = GetInterfaceInfo(NULL, &ulOutBufLen);
    if (dwRetVal == ERROR_INSUFFICIENT_BUFFER) {
        pInfo = (IP_INTERFACE_INFO *) MALLOC(ulOutBufLen);
        if (pInfo == NULL) {
            printf
                ("Unable to allocate memory needed to call GetInterfaceInfo\n");
            return 1;
        }
    }

// Make a second call to GetInterfaceInfo to get
// the actual data we need
    dwRetVal = GetInterfaceInfo(pInfo, &ulOutBufLen);
    if (dwRetVal == NO_ERROR) {
        printf("Number of Adapters: %ld\n\n", pInfo->NumAdapters);
        for (i = 0; i < pInfo->NumAdapters; i++) {
            printf("Adapter Index[%d]: %ld\n", i,
                   pInfo->Adapter[i].Index);
            printf("Adapter Name[%d]: %ws\n\n", i,
                   pInfo->Adapter[i].Name);
        }
//...

Zig could make this easier to do with a convenience method, i.e.

pub const IP_INTERFACE_INFO = extern struct {
    NumAdapters: i32,
    Adapter: [1]IP_ADAPTER_INDEX_MAP,
    pub fn AdapterSlice(self: *IP_INTERFACE_INFO) []IP_ADAPTER_INDEX_MAP {
        return @ptrCast([*]IP_ADAPTER_INDEX_MAP, &self.Adapter)[0 .. self.NumAdapters];
    }
};

The tricky part here would be knowing that NumAdapters is the length of the slice, but I think that info is available in the metadata.

Unable to generate bindings

Followed instructions on readme - throws an error.

W:\zigwin32gen>zig build genzig

loading 226 api json files...
1/226: loading 'AI.MachineLearning.DirectML.json'
read 124465 bytes
thread 12428 panic: reached unreachable code
C:\Users\kashifr\scoop\apps\ziglang\current\lib\std\debug.zig:226:14: 0x7ff67cfe1078 in std.debug.assert (genzig.obj)
if (!ok) unreachable; // assertion failure
^
W:\zigwin32gen\src\genzig.zig:1151:25: 0x7ff67d033c5a in CodeWriter::CodeWriter.writeBlock (genzig.obj)
std.debug.assert(s[s.len-1] == '\n');
^
W:\zigwin32gen\src\genzig.zig:670:26: 0x7ff67d01e1a7 in generateFile (genzig.obj)
try writer.writeBlock(
^
W:\zigwin32gen\src\genzig.zig:579:21: 0x7ff67d00f867 in readAndGenerateApiFile (genzig.obj)
try generateFile(module_dir, module, json_tree);
^
W:\zigwin32gen\src\genzig.zig:306:39: 0x7ff67cffe034 in main2 (genzig.obj)
try readAndGenerateApiFile(root_module, out_win32_dir, api_json_basename, file);
^
W:\zigwin32gen\src\genzig.zig:210:17: 0x7ff67cfe47ce in main (genzig.obj)
return main2() catch |e| switch (e) {
^
C:\Users\kashifr\scoop\apps\ziglang\current\lib\std\start.zig:458:37: 0x7ff67cfe36e4 in std.start.callMain (genzig.obj)
const result = root.main() catch |err| {
^
C:\Users\kashifr\scoop\apps\ziglang\current\lib\std\start.zig:255:65: 0x7ff67cfe3037 in std.start.WinStartup (genzig.obj)
std.os.windows.kernel32.ExitProcess(initEventLoopAndCallMain());
^
Unable to dump stack trace: FileNotFound
The following command exited with error code 2147483651 (expected 0):
cd W:\zigwin32gen && W:\zigwin32gen\zig-out\bin\genzig.exe
error: the following build command failed with exit code 1:
W:\zigwin32gen\zig-cache\o\a6258a072a6104458bfca3ecccfdf019\build.exe C:\Users\kashifr\scoop\apps\ziglang\current\zig.exe W:\zigwin32gen W:\zigwin32gen\zig-cache C:\Users\kashifr\AppData\Local\zig genzig

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    ๐Ÿ–– Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. ๐Ÿ“Š๐Ÿ“ˆ๐ŸŽ‰

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google โค๏ธ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.