ziglang / zig

General-purpose programming language and toolchain for maintaining robust, optimal, and reusable software.
https://ziglang.org
MIT License
34.81k stars 2.55k forks source link

Cannot `@cImport` `windows.h` when targetting `msvc` abi #20065

Open ofrank123 opened 5 months ago

ofrank123 commented 5 months ago

Zig Version

0.12.0

Steps to Reproduce and Observed Behavior

The following program:

const win = @cImport(@cInclude("windows.h"));

pub fn main() void {
    _ = win;
}

Fails to compile, using zig run -target x86_64-windows-msvc -lc .\main.zig:

C:\Users\olive\AppData\Local\zig\o\d6a404198b68dc019984cda1821a66b4\cimport.zig:71000:50: error: use of undeclared identifier 'struct_DECLSPEC_UUID'
pub inline fn MIDL_INTERFACE(x: anytype) @TypeOf(struct_DECLSPEC_UUID(x)) {
                                                 ^~~~~~~~~~~~~~~~~~~~
main.zig:1:13: error: C import failed: AnalysisFail
const win = @cImport(@cInclude("windows.h"));
            ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
referenced by:
    main: main.zig:4:9
    callMain: C:\bin\lib\std\start.zig:501:17
    remaining reference traces hidden; use '-freference-trace' to see all reference traces

Expected Behavior

It should compile

mjmlvp commented 5 months ago

There are reasons including windows.h does not work (perhaps someone can elaborate why).

The following may be of interest to you: https://www.youtube.com/watch?v=HsnWZxrf5VE https://github.com/marlersoft/zigwin32

I am not sure if the solution for interfacing with windows as described there, has been kept up to date all the way up to the present.

ofrank123 commented 5 months ago

It works fine using mingw in my experience, does mingw ship their own windows.h? But thanks for the links, I'll check it out

squeek502 commented 5 months ago

As a workaround, you can write bindings for the APIs you need, similar to those in the standard library:

https://github.com/ziglang/zig/blob/master/lib/std/os/windows/kernel32.zig#L72

or you can use https://github.com/marlersoft/zigwin32/ for autogenerated bindings.

The benefit of this approach is that you no longer need to link libc (if you're only linking it for windows.h), and your program will only depend on the DLLs that it actually uses.

ofrank123 commented 5 months ago

Thanks @squeek502, that's a good point. It'd be nice not to have to depend on libc as I don't really use it. I'll look into moving my codebase to use this strategy.

nihil-2019 commented 5 months ago

@ofrank123 yes, mingw ships their own headers. the reason this only happens on msvc & not mingw is because the windows SDK defines MIDL_INTERFACE like so:

#define MIDL_INTERFACE(x) struct DECLSPEC_UUID(x) DECLSPEC_NOVTABLE

while mingw just defines it as struct. as a simple workaround, if you define MIDL_INTERFACE like mingw does:

zig build-exe -target x86_64-windows-msvc -DMIDL_INTERFACE=struct -lc .\test.zig

then code that imports windows.h compiles fine.

ofrank123 commented 5 months ago

Thanks for the heads up @nihil-2019!

slimsag commented 5 months ago

Note: you can add @cDefine("MIDL_INTERFACE", "struct"); inside your @cImport({});