From my extremely limited perspective, this seems actually common. The Emacs source is full of the same kinds of things. I don’t know what that means, precisely, but it is interesting that they both reached for these tools to simplify data access.
Comparing the Emacs source and MRI is very instructive, down to Qnil. :)
Why are these macros rather than functions?
I think the rationale is, basically, for speed? That seems like a poor reason.
I think a macro can support “more” than functions. My memory is slightly fuzzy about C, so I can’t think of a great example.
Macros can do lots of things that functions can’t, but RARRAY_LEN and RARRAY_PTR don’t seem to be doing any of those things.
Speed is my guess too, but I’m not sure why – couldn’t they be inlined for exactly the same effect?