0

I am working on a project where I need to specify the information I get through UDP in a struct. The UDP sends structs in the form of packets which I need to unpack. Some of these packets contain an array of another struct. However, I get the error:

CS0650 Bad array declarator: To declare a managed array the rank specifier precedes the variable's identifier. To declare a fixed size buffer field, use the fixed keyword before the field type.

How do I do this correctly? I tried using the unsafe method, but that is only allowed for "standard" datatypes like: float, int, etc.

This is my struct where I want to put the data:

[StructLayout(LayoutKind.Explicit, Pack = 0, Size = 632)]
        public struct PacketSessionData
        {
            [FieldOffset(0)]
            public PacketHeader m_header;         // Header

            [FieldOffset(24)]
            public byte m_weather;                // Weather - 0 = clear, 1 = light cloud, 2 = overcast
                                                  // 3 = light rain, 4 = heavy rain, 5 = storm
            [FieldOffset(25)]
            public sbyte m_trackTemperature;        // Track temp. in degrees celsius
            [FieldOffset(26)]
            public sbyte m_airTemperature;          // Air temp. in degrees celsius
            [FieldOffset(27)]
            public byte m_totalLaps;              // Total number of laps in this race
            [FieldOffset(28)]
            public UInt16 m_trackLength;               // Track length in metres
            [FieldOffset(30)]
            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(31)]
            public sbyte m_trackId;                 // -1 for unknown, see appendix
            [FieldOffset(32)]
            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
            [FieldOffset(33)]
            public UInt16 m_sessionTimeLeft;       // Time left in session in seconds
            [FieldOffset(35)]
            public UInt16 m_sessionDuration;       // Session duration in seconds
            [FieldOffset(37)]
            public byte m_pitSpeedLimit;          // Pit speed limit in kilometres per hour
            [FieldOffset(38)]
            public byte m_gamePaused;                // Whether the game is paused – network game only
            [FieldOffset(39)]
            public byte m_isSpectating;           // Whether the player is spectating
            [FieldOffset(40)]
            public byte m_spectatorCarIndex;      // Index of the car being spectated
            [FieldOffset(41)]
            public byte m_sliProNativeSupport;    // SLI Pro support, 0 = inactive, 1 = active
            [FieldOffset(42)]
            public byte m_numMarshalZones;            // Number of marshal zones to follow
            [FieldOffset(43)]
            public MarshalZone m_marshalZones[21];             // List of marshal zones – max 21
            [FieldOffset(148)]
            public byte m_safetyCarStatus;           // 0 = no safety car, 1 = full
                                                     // 2 = virtual, 3 = formation lap
            [FieldOffset(149)]
            public byte m_networkGame;               // 0 = offline, 1 = online
            [FieldOffset(150)]
            public byte m_numWeatherForecastSamples; // Number of weather samples to follow
            [FieldOffset(151)]
            public WeatherForecastSample m_weatherForecastSamples[56];   // Array of weather forecast samples

            [FieldOffset(599)]
            public byte m_forecastAccuracy;          // 0 = Perfect, 1 = Approximate
            [FieldOffset(600)]
            public byte m_aiDifficulty;              // AI Difficulty rating – 0-110
            [FieldOffset(601)]
            public UInt32 m_seasonLinkIdentifier;      // Identifier for season - persists across saves
            [FieldOffset(605)]
            public UInt32 m_weekendLinkIdentifier;     // Identifier for weekend - persists across saves
            [FieldOffset(609)]
            public UInt32 m_sessionLinkIdentifier;     // Identifier for session - persists across saves
            [FieldOffset(613)]
            public byte m_pitStopWindowIdealLap;     // Ideal lap to pit on for current strategy (player)
            [FieldOffset(614)]
            public byte m_pitStopWindowLatestLap;    // Latest lap to pit on for current strategy (player)
            [FieldOffset(615)]
            public byte m_pitStopRejoinPosition;     // Predicted position to rejoin at (player)
            [FieldOffset(616)]
            public byte m_steeringAssist;            // 0 = off, 1 = on
            [FieldOffset(617)]
            public byte m_brakingAssist;             // 0 = off, 1 = low, 2 = medium, 3 = high
            [FieldOffset(618)]
            public byte m_gearboxAssist;             // 1 = manual, 2 = manual & suggested gear, 3 = auto
            [FieldOffset(619)]
            public byte m_pitAssist;                 // 0 = off, 1 = on
            [FieldOffset(620)]
            public byte m_pitReleaseAssist;          // 0 = off, 1 = on
            [FieldOffset(621)]
            public byte m_ERSAssist;                 // 0 = off, 1 = on
            [FieldOffset(622)]
            public byte m_DRSAssist;                 // 0 = off, 1 = on
            [FieldOffset(623)]
            public byte m_dynamicRacingLine;         // 0 = off, 1 = corners only, 2 = full
            [FieldOffset(624)]
            public byte m_dynamicRacingLineType;     // 0 = 2D, 1 = 3D
            [FieldOffset(625)]
            public byte m_gameMode;                  // Game mode id - see appendix
            [FieldOffset(626)]
            public byte m_ruleSet;                   // Ruleset - see appendix
            [FieldOffset(627)]
            public UInt32 m_timeOfDay;                 // Local time of day - minutes since midnight
            [FieldOffset(631)]
            public byte m_sessionLength;             // 0 = None, 2 = Very Short, 3 = Short, 4 = Medium, 5 = Medium Long, 6 = Long, 7 = Full
        };

And these are the structs from which I need to create an array in the previous struct:

[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)
        };

Edit:

After testing the solutions in the comments I get the following exception thrown: enter image description here

This is the code:

[MarshalAs(UnmanagedType.ByValArray, ArraySubType = UnmanagedType.Struct, SizeConst = 21)]
            [FieldOffset(43)]
            public MarshalZone[] m_marshalZones;             // List of marshal zones – max 21
            [FieldOffset(148)]
            public byte m_safetyCarStatus;           // 0 = no safety car, 1 = full
                                                     // 2 = virtual, 3 = formation lap
            [FieldOffset(149)]
            public byte m_networkGame;               // 0 = offline, 1 = online
            [FieldOffset(150)]
            public byte m_numWeatherForecastSamples; // Number of weather samples to follow
            [MarshalAs(UnmanagedType.ByValArray, ArraySubType = UnmanagedType.Struct, SizeConst = 56)]
            [FieldOffset(151)]
            public WeatherForecastSample[] m_weatherForecastSamples;   // Array of weather forecast samples
3
  • 1
    The CS0650 docs suggest using public MarshalZone[] m_marshalZones; (so no size). But how that works with [FieldOffset] I don't know Commented Jul 15, 2022 at 13:06
  • 2
    Check this answer: stackoverflow.com/a/25166809/6625167 Commented Jul 15, 2022 at 13:16
  • @HansKesting When I redo the code and remove all the offsets to make the struct layout sequentially, your answer has fixed the problem partially. However, this does still break my code since the MemoryMarshal.Cast function appearently is not capable of handling pointers and references Commented Jul 15, 2022 at 14:51

0

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.