It's simulated cleverly using a macro that wraps variable arguments in a struct literal: See the definition of http_set_cookie in https://github.com/boazsegev/facil.io/blob/master/lib/facil/...
If you like this, the book has some other tricks in it you might also like. (One example: you can define generic functions in C11).
I've seen people try to simulate this in C++ with tags.
Of course, the first comment on HN has the answer.
I am going to try this trick out today.
https://github.com/boazsegev/facil.io/blob/master/lib/facil/...
I've seen other hacks to do this, but this is the cleanest that I've seen. He uses the same name for the macro and the function.
The only thing I would change is the way the struct is passed. I would pass by reference.
I really like this.
Interesting. I expected taking the address of a struct literal to be illegal, but GCC and Clang both accept it. It does make sense, I guess.
But may I ask why you would pass it by reference? With old ABIs, the struct would be passed on the stack (i.e., by reference) anyway, and with more recent ones, a small prefix would be in registers but the rest passed by reference as well. So why bother manually cluttering the code?
Also if you set a struct with {1} the first field is set to 1 and the rest to 0. AFAIR it was always like that (at least since standardized C, but probably earlier).
Rust is built on LLVM, much like Clang. C integration is relatively easy. I think this is more viable than Go. Unfortunately, Rust is only portable to platforms LLVM supports. While that covers the majority of commonly used hardware today, it is not comprehensive. Also, Rust compile times are pretty bad, especially for optimized builds.
At the end of the day the author gets to write code in a language of their choice to scratch their own itch. End users don't care at all what language a web framework is written in.
No, it's not. None of the core data structures (String, Vec, HashMap, BTreeMap, VecDeque), for example, use it.
Rust is not a garbage collected language in any meaningful sense of the word. Its runtime is approximately the same size as C's, and the vast majority of all memory management in the Rust ecosystem is done with traditional malloc/free calls. The only difference between Rust and C at this level is that Rust inserts those calls for you automatically. In exchange, the space of programs accepted by the Rust compiler is smaller than what is accepted by a C compiler.
> At the moment it is a garbage-collected language but IIRC they are trying to move away from that as a requirement.
No, we're not. Because no such requirement exists and the vast majority of Rust code doesn't use reference counting at all. If anything, there are some folks that have looked into adding tracing garbage collection to Rust as a library.
The space of safe programs accepted by Rust is indeed smaller, but you can use the `unsafe` keyword if that is an issue. There are even automated transpilers from C to `unsafe` Rust.
https://words.steveklabnik.com/borrow-checking-escape-analys...
Edit: I see your other comment about the use of Arc and Rc in the stdlib, that is a good point. However, how much does that actually matter? I'm genuinely curious, my guess is that it is not significant, but I'm not well informed. For example, would that affect embedded use cases?
It's also probably way more portable than Golang or rust. That's also useful for the users of the webapp if they want to host it. I mean, it probably takes less effort to get it to compile and run on a system like SCO, compared to doing that with Golang or rust. You'd think legacy systems don't matter, but I imagine that there's still many businesses that heavily depend on such legacy systems because the costs to safely migrate are big.
Making it in C is probably also going to result in far smaller compiled code, since I imagine C requires a far smaller RTS than Golang or rust. That might make a difference for people that for some reason want to run a webapp on a small device.
I may be wrong though, since I don't have any experience with Golang or rust.
A good example is when using a String supplied by a scripting language such as Ruby or JavaScript.
Normally, you might need to copy the string to add a NUL byte, or request that the scripting engine provide a NUL terminated string (which might result in the same action performed).
Using this optional approach, a potential copy of the data can be avoided.
Though I guess it would be good to have nicer wrappers for the common case where you do only send text.
It's a bit unfortunate that they use two code paths for that which are basically just copy & paste.
https://github.com/boazsegev/facil.io/blob/master/lib/facil/...
You'd have to be a real maniac to serve TLS in someone's random C framework.
other than that, clever api
http://beej.us/guide/bgnet/html/single/bgnet.html#getaddrinf...