Hello I am working on a project where I have to cast a byte array from a UDP package into a data struct. This struct contains arrays with a fixed size. However, when casting the byte array with the following line:
var telemetry = MemoryMarshal.Cast<byte, F122_Stucts.PacketSessionData>(bytes);
I get the following exception:
Only value types without pointers or references are supported
It goes wrong with the MarshalZone and WeatherForecastSample arrays in the struct. My struct looks like this:
[StructLayout(LayoutKind.Sequential, Pack = 0, Size = 632)]
public struct PacketSessionData
{
public PacketHeader m_header; // Header
public byte m_weather; // Weather - 0 = clear, 1 = light cloud, 2 = overcast
// 3 = light rain, 4 = heavy rain, 5 = storm
public sbyte m_trackTemperature; // Track temp. in degrees celsius
public sbyte m_airTemperature; // Air temp. in degrees celsius
public byte m_totalLaps; // Total number of laps in this race
public UInt16 m_trackLength; // Track length in metres
public byte m_sessionType; // 0 = unknown, 1 = P1, 2 = P2, 3 = P3, 4 = Short P
// 5 = Q1, 6 = Q2, 7 = Q3, 8 = Short Q, 9 = OSQ
// 10 = R, 11 = R2, 12 = R3, 13 = Time Trial
public sbyte m_trackId; // -1 for unknown, see appendix
public byte m_formula; // Formula, 0 = F1 Modern, 1 = F1 Classic, 2 = F2,
// 3 = F1 Generic, 4 = Beta, 5 = Supercars
// 6 = Esports, 7 = F2 2021
public UInt16 m_sessionTimeLeft; // Time left in session in seconds
public UInt16 m_sessionDuration; // Session duration in seconds
public byte m_pitSpeedLimit; // Pit speed limit in kilometres per hour
public byte m_gamePaused; // Whether the game is paused – network game only
public byte m_isSpectating; // Whether the player is spectating
public byte m_spectatorCarIndex; // Index of the car being spectated
public byte m_sliProNativeSupport; // SLI Pro support, 0 = inactive, 1 = active
public byte m_numMarshalZones; // Number of marshal zones to follow
[MarshalAs(UnmanagedType.ByValArray, ArraySubType = UnmanagedType.Struct, SizeConst = 21)]
public MarshalZone[] m_marshalZones; // List of marshal zones – max 21
public byte m_safetyCarStatus; // 0 = no safety car, 1 = full
// 2 = virtual, 3 = formation lap
public byte m_networkGame; // 0 = offline, 1 = online
public byte m_numWeatherForecastSamples; // Number of weather samples to follow
[MarshalAs(UnmanagedType.ByValArray, ArraySubType = UnmanagedType.Struct, SizeConst = 56)]
public WeatherForecastSample[] m_weatherForecastSamples; // Array of weather forecast samples
public byte m_forecastAccuracy; // 0 = Perfect, 1 = Approximate
public byte m_aiDifficulty; // AI Difficulty rating – 0-110
public UInt32 m_seasonLinkIdentifier; // Identifier for season - persists across saves
public UInt32 m_weekendLinkIdentifier; // Identifier for weekend - persists across saves
public UInt32 m_sessionLinkIdentifier; // Identifier for session - persists across saves
public byte m_pitStopWindowIdealLap; // Ideal lap to pit on for current strategy (player)
public byte m_pitStopWindowLatestLap; // Latest lap to pit on for current strategy (player)
public byte m_pitStopRejoinPosition; // Predicted position to rejoin at (player)
public byte m_steeringAssist; // 0 = off, 1 = on
public byte m_brakingAssist; // 0 = off, 1 = low, 2 = medium, 3 = high
public byte m_gearboxAssist; // 1 = manual, 2 = manual & suggested gear, 3 = auto
public byte m_pitAssist; // 0 = off, 1 = on
public byte m_pitReleaseAssist; // 0 = off, 1 = on
public byte m_ERSAssist; // 0 = off, 1 = on
public byte m_DRSAssist; // 0 = off, 1 = on
public byte m_dynamicRacingLine; // 0 = off, 1 = corners only, 2 = full
public byte m_dynamicRacingLineType; // 0 = 2D, 1 = 3D
public byte m_gameMode; // Game mode id - see appendix
public byte m_ruleSet; // Ruleset - see appendix
public UInt32 m_timeOfDay; // Local time of day - minutes since midnight
public byte m_sessionLength; // 0 = None, 2 = Very Short, 3 = Short, 4 = Medium, 5 = Medium Long, 6 = Long, 7 = Full
};
The struct arrays look like this:
[StructLayout(LayoutKind.Explicit, Pack = 0, Size = 5)]
public struct MarshalZone
{
[FieldOffset(0)]
public float m_zoneStart; // Fraction (0..1) of way through the lap the marshal zone starts
[FieldOffset(4)]
public sbyte m_zoneFlag; // -1 = invalid/unknown, 0 = none, 1 = green, 2 = blue, 3 = yellow, 4 = red
};
[StructLayout(LayoutKind.Explicit, Pack = 0, Size = 8)]
public struct WeatherForecastSample
{
[FieldOffset(0)]
public byte m_sessionType; // 0 = unknown, 1 = P1, 2 = P2, 3 = P3, 4 = Short P, 5 = Q1
// 6 = Q2, 7 = Q3, 8 = Short Q, 9 = OSQ, 10 = R, 11 = R2
// 12 = R3, 13 = Time Trial
[FieldOffset(1)]
public byte m_timeOffset; // Time in minutes the forecast is for
[FieldOffset(2)]
public byte m_weather; // Weather - 0 = clear, 1 = light cloud, 2 = overcast
// 3 = light rain, 4 = heavy rain, 5 = storm
[FieldOffset(3)]
public sbyte m_trackTemperature; // Track temp. in degrees Celsius
[FieldOffset(4)]
public sbyte m_trackTemperatureChange; // Track temp. change – 0 = up, 1 = down, 2 = no change
[FieldOffset(5)]
public sbyte m_airTemperature; // Air temp. in degrees celsius
[FieldOffset(6)]
public sbyte m_airTemperatureChange; // Air temp. change – 0 = up, 1 = down, 2 = no change
[FieldOffset(7)]
public byte m_rainPercentage; // Rain percentage (0-100)
};
Is there any way I can convert this byte array into this structure?