I have an unmanaged struct containing fields whose byte offsets within it I want to determine. However, some of these fields are value tuples, and because value tuples are generic (EDIT: This is actually because ValueTuple uses LayoutKind.Auto
; see answer below), I can't use Marshal.OffsetOf
to determine the offset of any of the fields within the struct. (Even though it's not "marshal-able", it IS unmanaged and blittable to unmanaged memory.) Here's a trivialized example showing what I'm trying to do:
using System;
using System.Runtime.InteropServices;
IntPtr offset = Marshal.OffsetOf<TestStruct>(nameof(TestStruct.B)); // Throws exception
Console.WriteLine(offset);
[StructLayout(LayoutKind.Sequential, Pack=4)]
struct TestStruct
{
public int A;
public (int, int) B;
}
The above code throws an exception when calling Marshal.OffsetOf
:
Type 'TestStruct' cannot be marshaled as an unmanaged structure; no meaningful size or offset can be computed.
So how can I programmatically determine the offset of all of the fields within an unmanaged struct, but without using Marshal.OffsetOf
? I'm looking for a solution that will work on an arbitrary (unmanaged) struct type supplied via either generic parameter or Type object.
(Obviously, the above example is trivially easy to compute by hand. This is not my real-world example. My real-world use case is a library that uses reflection to iterate over all fields within arbitrary structs defined by the client application, and thus it is not possible to compute the offsets by hand.)