Packing and unpacking two 32-bit integers into an unsigned 64-bit integer
Union provides no guarantee of memory arrangement for this.  The C++ standard merely says that it's no bigger than the storage required for the largest element, and that it's designed to only have one active data member.

If you are only targeting one compiler and one architecture it may be okay to use it to translate between types, but it is definitely skiing off-piste.

I'd be tempted to wrap the whole thing up in a class and provide getter methods.  This insulates the user from changes in the implementation of the API in the most flexible way. And, use the bitwise operations (>>, &lt;&lt;, | and &amp;) inside the class.  These operations will happen on a register, rather than in memory, and therefore do not suffer for endian issues.