Live data from Hacker News

C Macro Reflection in Zig

jstrieb.github.io

91–100 of 139 posts

Re: C Macro Reflection in Zig

#91

Earlier quoted context omitted.

While I understand the reasoning, I think this is one of the most disappointing decisions by the Zig team. One of the main reasons I took Zig seriously was their C interop story—as someone who loves C and dislikes almost every implementation of C interop and FFI I’ve used in other languages (Rust is a notable exception to this), I was pretty much sold on Zig when I was able to, in a total of I respect Andrew a lot (I…

What's the problem? @cImport is becoming just @import.

> What's the problem? @cImport is becoming just @import.

You’re oversimplifying what’s actually a significant change.

Right now, I can do the following:

1. Download a prebuilt Zig release [0], on a fresh computer (zero prerequisites).

2. Implement a C library foo via foo.h and foo.c.

3. Compile foo.c into an object file foo.o via `zig cc`, using standard GNU-compatible compiler flags, for virtually any of the common (and even not-so-common) compilation targets.

4. Implement a Zig program bar via bar.zig.

5. Directly import foo.h into bar.zig via `@cImport` and use the C API as if it was Zig code.

6. Compile bar.zig and foo.o into a statically-linked executable baz via `zig build-exe`, for virtually any of the common (and even not-so-common) compilation targets.

No knowledge of the Zig build system and its semantics necessary. This is one of the most attractive aspects of Zig for a C programmer. I’ve gone through these exact steps with C programmers who thought Zig seemed interesting in theory but just didn’t want to have to learn a new ecosystem, build system, etc. The moment I showed them how quickly they could get up and running with Zig (and test it out with C code), without even having to install anything, it suddenly was impressive enough to experiment with.

The build system requirement may seem minor if you’re already a Zig programmer, but it’s massive if you want to attract C systems programmers.

[0]: https://ziglang.org/download

Re: C Macro Reflection in Zig

#92
post #2

@cImport is on the chopping block though [0]. You will still be able to import c files but it will require a little more work. This is because they want this functionality out of the language so they can remove libclang dependency. [0]: https://github.com/ziglang/zig/issues/20630

It will require a little more work in a trivial way, but not in a meaningful way. What's happening is that C imports are moving to the build system, instead of being a compiler builtin. It's part of making LLVM and libclang optional for programs which don't use it, but the use case of building C programs, and integrating C libraries with Zig programs, remains a central design goal. The build system is relatively new,…

> It just means that importing C libraries will be a build step, and not something you write directly into the relevant source code. This is not a big deal.

It 100% is a big deal. I explained this in another comment [0].

[0]: https://news.ycombinator.com/item?id=41111445

Re: C Macro Reflection in Zig

#93

Earlier quoted context omitted.

What's the problem? @cImport is becoming just @import.

> What's the problem? @cImport is becoming just @import. You’re oversimplifying what’s actually a significant change. Right now, I can do the following: 1. Download a prebuilt Zig release [0], on a fresh computer (zero prerequisites). 2. Implement a C library foo via foo.h and foo.c. 3. Compile foo.c into an object file foo.o via `zig cc`, using standard GNU-compatible compiler flags, for virtually any of the common…

I think someone who doesn't know what they are talking about about is asserting a build.zig requirement. I don't know for sure, but probably it will work with the command line?

Re: C Macro Reflection in Zig

#94
Example from the article:

    const win32 = @cImport({
        @cInclude("windows.h");
        @cInclude("winuser.h");
    });

    pub fn main() !void {
        _ = win32.MessageBoxA(null, "world!", "Hello", 0);
    }
Equivalent D:

    import windows, winuser;
    void main() {
        MessageBoxA(null, "world!", "Hello", 0);
    }
In essence pared it down to the essentials. The compiler figures out the rest.

Sometimes people ask for a special syntax for importing C files, but I like this simplicity so much better.

Re: C Macro Reflection in Zig

#95

Example from the article: const win32 = @cImport({ @cInclude("windows.h"); @cInclude("winuser.h"); }); pub fn main() !void { _ = win32.MessageBoxA(null, "world!", "Hello", 0); } Equivalent D: import windows, winuser; void main() { MessageBoxA(null, "world!", "Hello", 0); } In essence pared it down to the essentials. The compiler figures out the rest. Sometimes people ask for a special syntax for importing C files, bu…

Some of us like explicit invocations, not being unsure if something comes from a .h filenor some other importing mechanism (what if a .h file collides with another import mechanism)

Naked imports are also annoying. Which import did that MessageBoxA come from? windows? or winuser? Is it in the language kernel?

Explicit is better than implicit. The utter pain for the code writer of four or five keystrokes here and there is not worth confounding the code reader.

Re: C Macro Reflection in Zig

#96

Earlier quoted context omitted.

It will require a little more work in a trivial way, but not in a meaningful way. What's happening is that C imports are moving to the build system, instead of being a compiler builtin. It's part of making LLVM and libclang optional for programs which don't use it, but the use case of building C programs, and integrating C libraries with Zig programs, remains a central design goal. The build system is relatively new,…

> It just means that importing C libraries will be a build step, and not something you write directly into the relevant source code. This is not a big deal. It 100% is a big deal. I explained this in another comment [0]. [0]: https://news.ycombinator.com/item?id=41111445

I think you are operating from a mistaken understanding, as responded to in the linked comment.

Re: C Macro Reflection in Zig

#97

Example from the article: const win32 = @cImport({ @cInclude("windows.h"); @cInclude("winuser.h"); }); pub fn main() !void { _ = win32.MessageBoxA(null, "world!", "Hello", 0); } Equivalent D: import windows, winuser; void main() { MessageBoxA(null, "world!", "Hello", 0); } In essence pared it down to the essentials. The compiler figures out the rest. Sometimes people ask for a special syntax for importing C files, bu…

Some of us like explicit invocations, not being unsure if something comes from a .h filenor some other importing mechanism (what if a .h file collides with another import mechanism) Naked imports are also annoying. Which import did that MessageBoxA come from? windows? or winuser? Is it in the language kernel? Explicit is better than implicit. The utter pain for the code writer of four or five keystrokes here and ther…

Imports are found along the search path (just like .h files are searched for by the C preprocessor). The first one found it the one selected (just like the C preprocessor does).

> Which import did that MessageBoxA come from?

If it exists in two or more imports, the compiler will give an ambiguity error. To resolve the ambiguity error, qualify the call with the name of the import:

    windows.MessageBoxA(null, "world!", "Hello", 0);
or, one can do this:

    import windows : MessageBoxA;
or this:

    import windows, winuser;
    alias MessageBoxA = windows.MessageBoxA;
You can be as explicit as you like, and don't need to worry about ambiguity because the compiler will issue an error for that. It works the same way for D imports.

Re: C Macro Reflection in Zig

#98
post #54

Earlier quoted context omitted.

See these posts on the LLVM issue by Andrew. They clearly state that this functionality isn't going anywhere, just the method of achieving said functionality is changing: https://github.com/ziglang/zig/issues/16270#issuecomment-161... https://github.com/ziglang/zig/issues/16270#issuecomment-161...

Not involved with Zig at all, but this comment is a bit concerning : > This is not the first controversial change I have made to the Zig project, and it won't be the last. I have a vision, and I know how to execute it. People are often surprised by what Zig has accomplished, and they wonder why other projects have not done what Zig does. Well, you are seeing the magic right now. I ignore the peanut gallery and do wha…

> He's probably brillant and all but this ... feels like hubris.

I don’t think it’s hubris, because Andrew’s results speak for him, but it’s certainly alienating, to be honest.

Although I understand the struggle of having to prioritize opinions and perspectives, it comes across like Andrew only values the opinions and perspectives of very specific folks, whom he often calls out.

Here’s what I mean: I love Zig and I write a lot of Zig code, especially within the past year (almost daily), but none of the Zig code I’ve been working on is publicly available or open-source (although I hope I can open-source various components soon, fingers crossed). I’ve gained a lot of valuable experience with Zig—including successfully convincing folks (mainly C programmers) to use it who wouldn’t have tried it otherwise. When I read these interactions, even though I have thoughts I’d like to share as a committed user who wants to see the project succeed and gain mainstream adoption, I get the feeling that my thoughts aren’t welcome since I don’t have a huge Zig project or something, so I just keep my thoughts to myself. Andrew seems to mostly care about feedback from the creators of Bun, TigerBeetle, etc., which, if I’m correct, is fine (it’s his project and therefore his right), but I imagine there are plenty of users like me who aren’t just part of “the peanut gallery” yet staying out of it to avoid the drama.

Re: C Macro Reflection in Zig

#99

Earlier quoted context omitted.

Some of us like explicit invocations, not being unsure if something comes from a .h filenor some other importing mechanism (what if a .h file collides with another import mechanism) Naked imports are also annoying. Which import did that MessageBoxA come from? windows? or winuser? Is it in the language kernel? Explicit is better than implicit. The utter pain for the code writer of four or five keystrokes here and ther…

Imports are found along the search path (just like .h files are searched for by the C preprocessor). The first one found it the one selected (just like the C preprocessor does). > Which import did that MessageBoxA come from? If it exists in two or more imports, the compiler will give an ambiguity error. To resolve the ambiguity error, qualify the call with the name of the import: windows.MessageBoxA(null, "world!", "…

Compiler giving a compiler error still favors the writer, not the reader of code. It seems like in its design in general D favors the writer of code with all its complicated bells and whistles that one must keep in mind as a reader. I think decades of experience has shown us that it is way better to favor the reader.

Re: C Macro Reflection in Zig

#100
post #71

Earlier quoted context omitted.

> common case-conventions Unfortunately, we must not forget forget ABOMINATIONCase and NAMESPACED_PascalCase (we could also generalize this to any switch from one convention to another after the first word). I've found they usually are, in fact, identifiable and roundtrippable. I've found the following usually works (it fails for multi-word prefixes or non-leading exceptions, and of course single-word identifiers are…

I mean, there can always be a function on the TranslateC step which maps 'special case' names (or even translate them to an entirely different name, for instance when there's collisions with Zig reserved keywords): translateSpecialCaseNames(.{ .{ .src = "ABOMINATIONCase", .dst = "case" }, .{ .src = "NAMESPACED_PascalCase", .dst = "pascalCase" }, }); ...in my own language bindings generator, being able to define such…

Reserved words really shouldn't require manual care; "list of keywords in X language" is really easy to handle so you can just append an underscore.

I do think that namespaces need to be semi-manually managed though (likely only at the project level), since often there are things that look like a namespace but shouldn't be treated like one, and it's not always obvious from a single identifier how many words should be treated as the namespace in some styles.

One special case is that sometimes C-ish libraries have class-likes like {Foo, FooBar, FooBaz} where the desired mapping is {foo.Foo, foo.Bar, foo.Baz}.

Post reply on HN