Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How do I convert a C# byte array into structured data?

Tags:

c#

struct

I am passing 64 byte data packets over USB to a microcontroller. In the microcontroller C code the packets have the structure,

typedef union
{
    unsigned char data[CMD_SIZE];
    cmd_get_t get;
    // plus more union options
} cmd_t;

with

typedef struct
{
    unsigned char cmd;          //!< Command ID
    unsigned char id;           //!< Packet ID
    unsigned char get_id;       //!< Get identifier
    unsigned char rfu[3];       //!< Reserved for future use
    union
    {
        unsigned char data[58];     //!< Generic data
        cmd_get_adc_t adc;          //!< ADC data
        // plus more union options
    } data;                     //!< Response data
} cmd_get_t;

and

typedef struct
{
    int16_t supply;
    int16_t current[4];
} cmd_get_adc_t;

On the PC side in C# I have been provided with a function which returns the 64 byte packet as a Byte[]. The function uses Marshal.Copy to copy the received data into the Byte[] array. I then used a C# struct of the form

[StructLayout(LayoutKind.Sequential, Pack=1)]
    public struct COMMAND_GET_ADC
    {
        public byte CommandID;
        public byte PacketID;
        public byte GetID;
        [MarshalAs(UnmanagedType.ByValArray, SizeConst=3)]
            public byte[] RFU;
        public short Supply;
        [MarshalAs(UnmanagedType.ByValArray, SizeConst=4)]
            public short[] Current;
    }

and again used Marshal.Copy to copy the byte array into the struct so that I could work with is as structured data, e.g.

COMMAND_GET_ADC cmd = (COMMAND_GET_ADC)RawDeserialize(INBuffer, 1, typeof(COMMAND_GET_ADC));
short supply = cmd.Supply;

with

public static object RawDeserialize(Byte[] rawData, int position, Type anyType)
{
    int rawsize = Marshal.SizeOf(anyType);
    if(rawsize > rawData.Length)
    {
        return null;
    }
    IntPtr buffer = Marshal.AllocHGlobal(rawsize);
    Marshal.Copy(rawData, position, buffer, rawsize);
    object retobj = Marshal.PtrToStructure(buffer, anyType);
    Marshal.FreeHGlobal(buffer);
    return retobj;
}

This just feels like I am making lots of copies of the data and like it might not be the most productive way of achieving what I want to. I also need to convert the structured data back to a byte array for commands to the device. I have a method which uses the same process (i.e. use a struct and then serialise it to a byte array and pass the byte array to the write function).

Are there better alternatives?

like image 918
Duncan Drennan Avatar asked Nov 25 '10 07:11

Duncan Drennan


People also ask

How do you convert F to C easily?

To convert temperatures in degrees Fahrenheit to Celsius, subtract 32 and multiply by .5556 (or 5/9).

How do you convert AC to DC voltage?

The most common way to convert alternating current into direct current is to use one or more diodes, those handy electronic components that allow current to pass in one direction but not the other. Although a rectifier converts alternating current to direct current, the resulting direct current isn't a steady voltage.

How do you convert back to Celsius?

A calculator helps here. To convert Fahrenheit to Celsius, subtract 32 degrees and divide by 1.8. To convert Celsius to Fahrenheit, multiply by 1.8 and add 32 degrees.


1 Answers

If you can use unsafe code, you can cast the byte array to a pointer to your structure using the 'fixed' keyword.

like image 141
logicnp Avatar answered Oct 30 '22 05:10

logicnp