C
C#2mo ago
Rai

MemoryMarshal.Cast on a struct with array of known fixed size

I'm wondering if there is some way to marshal a byte array into a struct that is known to be of fixed size, or has known length values via other fields:
using System.Runtime.InteropServices;
using System.Text.Json;

Span<byte> buffer = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20];
Console.WriteLine(buffer.Length == Marshal.SizeOf<TestStruct>());
var tstruct = MemoryMarshal.Cast<byte, TestStruct>(buffer)[0];
Console.WriteLine(JsonSerializer.Serialize(tstruct));
Console.WriteLine(tstruct.b);

[StructLayout(LayoutKind.Explicit, Size = 20)]
public struct TestStruct
{
[FieldOffset(0)] [MarshalAs(UnmanagedType.ByValArray, ArraySubType = UnmanagedType.I4, SizeConst = 4)]
public int[] arr;

[FieldOffset(16)] [MarshalAs(UnmanagedType.I4)]
public int b;
}
using System.Runtime.InteropServices;
using System.Text.Json;

Span<byte> buffer = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20];
Console.WriteLine(buffer.Length == Marshal.SizeOf<TestStruct>());
var tstruct = MemoryMarshal.Cast<byte, TestStruct>(buffer)[0];
Console.WriteLine(JsonSerializer.Serialize(tstruct));
Console.WriteLine(tstruct.b);

[StructLayout(LayoutKind.Explicit, Size = 20)]
public struct TestStruct
{
[FieldOffset(0)] [MarshalAs(UnmanagedType.ByValArray, ArraySubType = UnmanagedType.I4, SizeConst = 4)]
public int[] arr;

[FieldOffset(16)] [MarshalAs(UnmanagedType.I4)]
public int b;
}
Althought due to MarshalAs it should be known that it's up to 4 elements this wouldn't work due to the array being recognized as a pointer/reference type. Is there a way to do this without having to enable unsafe and abuse the fixed keyword?
3 Replies
reflectronic
reflectronic2mo ago
MarshalAs has no relationship to MemoryMarshal you either need to use a fixed buffer or an inline array. it is impossible to make this work with int[] in a "free" way. you could get it to work using Marshal.PtrToStructure but it is the same as manually assigning instances of the struct in a loop
MODiX
MODiX2mo ago
reflectronic
sharplab.io (click here)
Span<byte> buffer = [10, 0, 0, 0, 50, 0, 0, 0, 25, 0, 0, 0...
Console.WriteLine(buffer.Length == Unsafe.SizeOf<TestStruc...
var tstruct = MemoryMarshal.Read<TestStruct>(buffer);
Console.WriteLine(tstruct.b);
Console.WriteLine();
foreach (var elt in tstruct.arr) {
Console.WriteLine(elt);
}
struct TestStruct {
public Int4 arr;
// 7 more lines. Follow the link to view.
Span<byte> buffer = [10, 0, 0, 0, 50, 0, 0, 0, 25, 0, 0, 0...
Console.WriteLine(buffer.Length == Unsafe.SizeOf<TestStruc...
var tstruct = MemoryMarshal.Read<TestStruct>(buffer);
Console.WriteLine(tstruct.b);
Console.WriteLine();
foreach (var elt in tstruct.arr) {
Console.WriteLine(elt);
}
struct TestStruct {
public Int4 arr;
// 7 more lines. Follow the link to view.
React with ❌ to remove this embed.
Rai
Rai2mo ago
Thank you very much I completely forgot that the InlineArray attribute exists. This will make life easier.
Want results from more Discord servers?
Add your server