Open Radvendii opened 1 month ago
Thanks for the recatogrization, I wasn't sure if it was a bug or proposal.
I don't know how the tags work, so maybe this is correct anyways, but I didn't invoke zig translate-c
at any point, this is just from @cImport()
and @cInclude()
I've uncovered even weirder behaviour. In stdbool.h
, we have bool
defined by #define bool _Bool
, so I figured if I overrode this by putting
@cInclude("stdbool.h");
@cUndef("bool");
@cDefine("bool", "int");
To the top of the @cImport()
statement i would force zig to define @"bool" = c_int
so that the example works,
It doesn't work. Still defines @"bool" = bool
. However, wherever bool
is used as part of a struct, it now uses c_int
.
Totally unsure what's going on now. Is mapping C bool
to zig bool
hard-coded? Is re-#define
ing things not supported?
Okay, it seems indeed that this is a general thing. any time you have
const c = @cImport({
@cDefine("foo", "1");
@cUndef("foo");
@CDefine("foo", "2");
});
It's going to correctly apply the second #define
in any C code @cInclude
d later on (replacing foo
with 2
), but if you access that as a variable from zig, it will go with the first definition (c.foo == 1
).
I can't tell how much of this is intentional design vs. bugs. #define
s don't actually have the same semantics as const
declarations, but my intuition is that whatever the last #define
declaration is, that one should determine how it shows up in the zig code, since that's how it would show up in C code with the same set of #include
s and #define
s
More minimal foo.h
:
#define bool _Bool
#define true 1
#define false 0
The last 3 lines of zig translate-c foo.h
:
pub const @"bool" = bool;
pub const @"true" = @as(c_int, 1);
pub const @"false" = @as(c_int, 0);
I have a pretty janky workaround:
@cImport({
@cDefine("true", "(_Bool)1");
@cDefine("false", "(_Bool)0");
@cInclude("stdbool.h");
@cUndef("true");
@cUndef("false");
@cDefine("true", "(_Bool)1");
@cDefine("false", "(_Bool)0");
// other @cInclude()s that use stdbool.h...
});
A couple of points of explanation:
(_Bool)1
, not (bool)1
. The latter confuses zig and it just doesn't understand what the 1 is doing theretrue
and false
. If we only define it before, stdbool.h
will override, and if we only define it after, zig will use the first definition (from stdbool.h
) to generate its own idea of what true
and false
are.stdbool.h
but with altered definitions of true
and false
if we were so inclined, it's not that long of a file.It generates
pub const @"true" = @import("std").zig.c_translation.cast(bool, @as(c_int, 1));
pub const @"false" = @import("std").zig.c_translation.cast(bool, @as(c_int, 0));
Which is kind of goofy, but does work.
Zig Version
0.13.0-dev.46+3648d7df1
Steps to Reproduce and Observed Behavior
Explanation below, but it's easier to see than explain. I've created a minimal reproduction so you can
The error I get
The issue is with
#include <stdbool.h>
from c-code, and then referencing values from zig.bool
gets mapped to zigbool
, buttrue
andfalse
get mapped toc_int
s, so a bool defined in c code can't be used as a bool when interfacing with that c code.In particular, the generated zig code looks like
Expected Behavior
It's tricky. I understand why
bool
would get mapped tobool
, and I understand why#define false 0
instdbool.h
would get translated to ac_int
. There's nothing "buggy" about either of those individually. But together they make interfacing with C code that makes use of bools kind of unworkable.Assigning a c-defined bool to a c-defined bool-type variable seems like it should just work.