New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
C interop: returning structs by value from imported C functions looses content #3211
Comments
PS: when building with the stable zig 0.4.0+ version, I get the "junk" behaviour where the result differs between runs, e.g. one run is:
And another run is:
(note how for instance .msaa_render_targets is true in one run and false in the next. |
Thanks for the report! I don't think there is enough time to get this in for 0.5.0 but definitely want to fix this. |
No worries! |
This seems to work fine on 0.5.0 and windows :)
|
I'll give it another try in the evening (a few hours from now) on macOS (I'll test both with the 0.5.0 release and the current HEAD version). |
Ok, I just tested the 0.5.0 release on macOS (Cataline Beta) and I still see the faulty behavior. Strange that it would behave differently between Mac and Windows. I used the precompiled tar.xz Zig distribution instead of the homebrew version, because compiling the LLVM dependency fails for some reason on the macOS Catalina Beta. |
The C function compiles to:
So, it's returning short structs in registers. The call site:
So, it's expecting the struct to be on the stack. |
Should |
Just cloned it now. Had to add Changing the build script for .x86_64, .linux, .gnu means I'm getting all |
Some new info from my side (since I noticed some more strange behaviour while continuing on my Sokol-header Zig bindings): The returned struct size matters: the problem only appears if the return-struct is <= 16 bytes. If the struct size is above 16 bytes, the returned struct is not corrupted (tested on Linux and Mac). To verify just add an https://github.com/floooh/zig-test/blob/6b97b330eafd0515ba22a555c5e31c19aa39dedb/src/test.h#L10 ...then do another I also found out that once such a "return value corruption" happens, the function parameters of a function which returns such a <16 bytes struct may also get corrupted. This 16-bytes cutoff looks to me like it's an ABI issue. |
Indeed, it's a known limitation of stage1 but it looks like nobody's linked #1481 yet. |
Just a heads up, it seems this issue is fixed in the current zig 0.9.0 dev version. I no longer need to pad small C struct args and return values to get above 16 bytes on macOS. |
I stumbled over a curious problem today while continuing with the Zig bindings for my C headers. Some of my C functions return structs by value, and those returned structs don't arrive with their content intact on the Zig side.
I wrote a minimal reproduction test case:
https://github.com/floooh/zig-test
When you do a
zig build run
in there you should see output like this:Note how the values under
C struct
are different from the values underZig struct
, they should be the same (all should be "true")The project consists of a C header/source pair test.h/.c and the Zig main file test.zig.
The C part mainly defines a function
query_features
which returns a struct by value made entirely of bools, and all bools are set to true:https://github.com/floooh/zig-test/blob/d8a409e621e1f635cad07e08ac829ccb22971ff3/src/test.c#L5-L16
There's also another C function which calls the
query_features
function and prints the content of the returned struct. This is used to check that returning the struct works in C:https://github.com/floooh/zig-test/blob/d8a409e621e1f635cad07e08ac829ccb22971ff3/src/test.c#L19-L29
The Zig main file imports the C header and calls both functions
https://github.com/floooh/zig-test/blob/d8a409e621e1f635cad07e08ac829ccb22971ff3/src/test.zig#L1-L20
Here's the problem:
https://github.com/floooh/zig-test/blob/d8a409e621e1f635cad07e08ac829ccb22971ff3/src/test.zig#L11
The returned Zig struct imported from C seems to have lost its content. In this test I always get a struct back that's entirely filled with "false", but in more interesting cases (my C headers) the content changes from run to run, as if the struct contains junk.
Another interesting effect is that when I change all the bools in the C struct to int, then the expected content is returned (all 1's).
The Zig version is compiled from HEAD from a few days ago, OS is macOS.
The text was updated successfully, but these errors were encountered: