If you are under the impression that an intermediate expanded file is produced, then you misunderstand how Lisp macros work.
This is not groundbreaking per se, but it is certainly a smart compile-time tactic of interfacing with a C ABI.
When you use autoconf, you typically run configure, then you're left with a config.h, which then parameterizes later builds.
On the other hand, when you evaluate the the definition of dirent->name, no intermediate file is left behind.
Of course in both cases you make temporary C files, but they are ephemeral. The difference is that in the first case you are generating files for inclusion in a later phase, and in the second you are effectively extending your scheme compiler with a c compiler.
The surprising about this code from a Scheme programmer's POV is that usually macros are about rewriting Scheme source using Scheme. In this case the macro generates C source, forks to compile and run it, and munges the result into the resulting text.
But sure, I can see that from a certain point of view, autoconf and scheme macros can do similar things :)
Further, packing can depend upon the pragma in force when the header file is included. How to set up that environment?
What Guile has now is the "list-all-members-in-the-struct" approach that Klock discourages. It's the difference between API and ABI compatibility. I'd like to figure out how to do the former.