PChar and dynamic arrays are stored in memory with a 32-bit integer at [-1] that denotes the actual length. For PChar that is invisible, as their length should be decided by the first #0 char. But that means that the compiler can treat a PChar as a regular one.
So, a struct like this:
typedef struct {
GUID PowerSetting;
DWORD DataLength;
UCHAR Data[1];
}
is actually how you would convert a dynamic Pascal array to C...

For comparison, the last large project I worked on (bug fixing) was written in C++, and fully static. No dynamic memory at all. There was this huge struct filled with other nested structs, that was written as-is from memory to disk and vice versa. Just save 1 record of size sizeof() to disk, or take the global pointer and load that amount of bytes into it. Oh, yes, did I mention that everything was defined globally?
And with each new version , new stuff was added. To the end of the file, of course. And if you changed any of the record packing settings, everything stopped working. You couldn't actually reference any of the structs inside, as their location and size was defined by the version of the program. It was a lot of fun making bugfixes for that...
And all of you say: "Well, of course that should be possible to do in FPC as well, because some programs work like that and we should be able to communicate with that." Instead of the sane approach: writing in/export functions.