Are "blittable types" really unmanaged types for StructLayout Sequential

67 Views Asked by At

EDIT: My question is not about the difference between blittable and unmanaged but about what exactly does the documentation for StructLayoutAttribute mean. One can still see term "blittable" and not "unmanaged" being used in this issue from 2022.

The official documentation for the StructLayoutAttribute states:

For blittable types, LayoutKind.Sequential controls both the layout in managed memory and the layout in unmanaged memory. For non-blittable types, it controls the layout when the class or structure is marshaled to unmanaged code, but does not control the layout in managed memory.

From this list of Blittable and Non-Blittable Types, System.Boolean is non-blittable.

However, the following struct will have the sequential layout in managed memory although it contains the non-blittable (but unmanaged) bool field.

[StructLayout(LayoutKind.Sequential)]
struct Unmanaged {
    public byte b1;
    public int i1;
    public bool bool1;
    public byte b2;
    //public string str; // -> uncomment to have auto layout

    public unsafe override string ToString() {

        //https://forum.unity.com/threads/question-about-size-and-padding-of-a-type-in-c.1274090/
        var b1FieldOffset = (long)Unsafe.AsPointer(ref this.b1) - (long)Unsafe.AsPointer(ref this);
        var i1FieldOffset = (long)Unsafe.AsPointer(ref this.i1) - (long)Unsafe.AsPointer(ref this);
        var b2FieldOffset = (long)Unsafe.AsPointer(ref this.b2) - (long)Unsafe.AsPointer(ref this);
        var bool1Offset = (long)Unsafe.AsPointer(ref this.bool1) - (long)Unsafe.AsPointer(ref this);

        var sb = new StringBuilder();
        sb.AppendLine($"Size:      {Unsafe.SizeOf<Unmanaged>()}");
        sb.AppendLine($"b1 Offset: {b1FieldOffset}");
        sb.AppendLine($"i1 Offset: {i1FieldOffset}");
        sb.AppendLine($"bool1 Offset: {bool1Offset}");
        sb.AppendLine($"b2 Offset: {b2FieldOffset}");

        return sb.ToString();
    }
}

ToString will output:

Size:      12
b1 Offset: 0
i1 Offset: 4
bool1 Offset: 8
b2 Offset: 9

If we uncomment the string field which is both non-blittable AND not unmanaged, we would get the following managed memory layout (sequential is disregarded):

Size:      16
b1 Offset: 12
i1 Offset: 8
bool1 Offset: 13
b2 Offset: 14

After already providing feedback w.r.t an outdated tutorial for the Pack field in the same documentation (decimal being 2 4byte fields and 1 8byte field as of .NET5+ and not 4 4byte fields), I suspect that the documentation regarding blittable/non-blittable may be out of date and what it really means is unmanaged/managed per Unmanaged types

Should I post another feedback for the documentation to change or is my suspicion unfounded?

0

There are 0 best solutions below