What you're doing with this union (writing to one field and reading from another) is called type punning, and you have to be really careful when doing it; LuaJIT has strict rules around doing things like this (to allow better optimizations), and the behavior you're experiencing is a result of that. Basically, the FFI's rules don't always line up
with those of Lua itself; this is one of them.
LuaJIT allows type punning, but only if it's explicitly done via a union access
; using raw pointers (or arrays or whatever) for this purpose isn't allowed. By doing just `u8`, for example, the JIT only sees an access to the raw pointer and "forgets" that it actually came from a union. Oops. By doing `union.u8`, the JIT can now see the whole union access and therefore allows the type punning, which then works as expected.
In general, you don't want to localize cdata lookups like this, anyway; the JIT is perfectly capable of doing that on its own. In fact it was designed
to do it on its own!