Welcome to OStack Knowledge Sharing Community for programmer and developer-Open, Learning and Share
Welcome To Ask or Share your Answers For Others

Categories

0 votes
575 views
in Technique[技术] by (71.8m points)

marshalling - Marshal Reads a structure from a ushort array C#

I am trying to read the structure from the byte array:

var data = new ushort[10]{65535, 65535, 65535 ...};
var datashort = ChangeUshortToShort(data);
FromArray(datashort )

And my structur:

[StructLayout(LayoutKind.Sequential, Pack = 1)]
public class Failures
{
    public ushort cardTrErr;
    public uint TrErr;
    public uint KsrErr;
    public ushort sh6;
    public ushort sh12;
    public ushort blockade;
    public ushort biz;
    public ushort blockadeInPerm;

    public virtual byte[] ToArray()
    {
        int size = Marshal.SizeOf(this);
        IntPtr ptr = Marshal.AllocHGlobal(size);
        Marshal.StructureToPtr(this, ptr, false);
        byte[] array = new byte[size];
        Marshal.Copy(ptr, array, 0, size);
        Marshal.FreeHGlobal(ptr);
        return array;
    }

    public virtual void FromArray(short[] val)
    {
        int size = Marshal.SizeOf(this);
        IntPtr ptr = Marshal.AllocHGlobal(size);
        Marshal.Copy(val.ToArray(), 0, ptr, size);
        Marshal.PtrToStructure(ptr, this);
        Marshal.FreeHGlobal(ptr);
    }
    public short[] ChangeUshortToShort(ushort[] val)
    {
        List<short> list = new List<short>();
        foreach (var item in val)
        {
            list.Add((short)(item & 0xFF));
            list.Add((short)(item >> 8));
        }
        return list.ToArray();
    }
}

Method ChangeUshortToShort return array with all values 255.

When I do ToArray() it to return 255. But if I do it FromArray() it assigns 255 value for ushort when should 65535. And assigns 16711935 for uint when should be 4294967295.

I think i should use attributes MarshalAs, but dont know how. Can someone help me?

Edit:

Second structure:

[StructLayout(LayoutKind.Sequential, Pack = 1)]
public struct Flags
{
    public ushort frameCnt;
    public ushort progVersion;
    public byte algUM;
    public byte deviceNumber;
    public _alg_1U _alg_1U;
    public ushort OUTPUTS;
    public _statS _StatS1;
    public _statS2 _StatS2;
    //public ushort _StatS1;
    //public ushort _StatS2;
    public ushort nbLector;
    public ushort nbSignal;
    public byte comBlockadeT1;
    public byte comBlockadeT2;
    public _permS permS;
    //public ushort permS;
    public ushort permHistory;
    public ushort stopInfo;
    public _controlFlagsS _controlFlagsS;
    //public ushort _controlFlagsS;
    public ushort timerInfo;
    public ushort timerTrDiagCycle;
    public ushort sizeOfStruct;
    public ushort methanSensorValue1;
    public ushort methanSensorValue2;
    public ushort methanSensorValue3;
    public ushort methanSensorValue4;
}
[StructLayout(LayoutKind.Sequential, Pack = 1)]
public struct _alg_1U
{
    public byte PZP1;
    public byte PZP2;
    public byte PZS;
    public byte PZZ1;
    public byte PZZ2;
    public byte PZZ3;
    public byte KB1;
    public byte KB2;
    public byte KRU;
    public byte reserved;
}
[StructLayout(LayoutKind.Sequential, Pack = 1)]
public struct _statS
{
    public bool SYS_AW;
    public bool SYS_BK;
    public bool SYS_READY;
    public bool SYS_WORK;
    public bool PT_WORK;
    public bool DISPATCHER_ON_LINE;
    public bool SYS_STARTING;
    public bool LEKTOR_ERROR;
    public bool SYS_BK_KSR;
    public bool SYS_READY_LEKTOR;
    public bool SYS_INIT;
    public bool KRU_WORK;
    public bool SIG_RES_DIODA;
    public bool SIG_RES_BK_KSR;
    public bool SIG_RES_WORK;
    public bool unUse16;
}
[StructLayout(LayoutKind.Sequential, Pack = 1)]
public struct _statS2
{
    public bool R1;
    public bool R2;
    public bool SAG_DISABLED;
    public bool unUse4;
    public bool unUse5;
    public bool unUse6;
    public bool unUse7;
    public bool unUse8;
    public bool unUse9;
    public bool unUse10;
    public bool unUse11;
    public bool unUse12;
    public bool unUse13;
    public bool unUse14;
    public bool unUse15;
    public bool unUse16;
}
[StructLayout(LayoutKind.Sequential, Pack = 1)]
public struct _permS
{
    public bool PZP1;
    public bool PZP2;
    public bool PZS;
    public bool PZZ1;
    public bool PZZ2;
    public bool PZZ3;
    public bool KOMBAJN1;
    public bool KOMBAJN2;
    public bool KRU;
    public bool PT;
    public bool unUse11;
    public bool unUse12;
    public bool unUse13;
    public bool unUse14;
    public bool unUse15;
    public bool unUse16;
}
[StructLayout(LayoutKind.Sequential, Pack = 1)]
public struct _controlFlagsS
{
    public bool confSaved;
    public bool confFrameErr;
    public bool confDataErr;
    public bool passSaved;
    public bool passFrameErr;
    public bool unUse6;
    public bool unUse7;
    public bool unUse8;
    public bool unUse9;
    public bool unUse10;
    public bool unUse11;
    public bool unUse12;
    public bool unUse13;
    public bool unUse14;
    public bool unUse15;
    public bool unUse16;
}
question from:https://stackoverflow.com/questions/65885606/marshal-reads-a-structure-from-a-ushort-array-c-sharp

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
Welcome To Ask or Share your Answers For Others

1 Answer

0 votes
by (71.8m points)

If the intention is to re-interpret the 20 bytes of data directly, they you're probably doing things the hard way; consider:

using System;
using System.Runtime.InteropServices;

[StructLayout(LayoutKind.Sequential, Pack = 1)]
public struct Failures
{
    public ushort cardTrErr;
    public uint TrErr;
    public uint KsrErr;
    public ushort sh6;
    public ushort sh12;
    public ushort blockade;
    public ushort biz;
    public ushort blockadeInPerm;
}
static class P
{
    static void Main()
    {
        var data = new ushort[10];
        for (int i = 0; i < data.Length;i++) data[i] = 65535;

        // re-interpret
        Failures failures = MemoryMarshal.AsRef<Failures>(
            MemoryMarshal.Cast<ushort, byte>(data));
        // show the data
        Console.WriteLine(failures.cardTrErr);
        Console.WriteLine(failures.TrErr);
        Console.WriteLine(failures.KsrErr);
        Console.WriteLine(failures.sh6);
        Console.WriteLine(failures.sh12);
        Console.WriteLine(failures.blockade);
        Console.WriteLine(failures.biz);
        Console.WriteLine(failures.blockadeInPerm);
    }
}

Note, however, that re-interpret casts like this are an endianness nightmare; it would be worth making some CPU-endianness assertions, at a minimum (i.e. if the data is little-endian, throw an exception if your CPU isn't)

If you don't have access to spans, the same result can be achieved via unsafe:

        Failures failures;
        unsafe
        {
            fixed (ushort* ptr = data)
            {   // re-interpret
                failures = *(Failures*)ptr;
            }
        }
        // show the data
        Console.WriteLine(failures.cardTrErr);
        Console.WriteLine(failures.TrErr);
        Console.WriteLine(failures.KsrErr);
        Console.WriteLine(failures.sh6);
        Console.WriteLine(failures.sh12);
        Console.WriteLine(failures.blockade);
        Console.WriteLine(failures.biz);
        Console.WriteLine(failures.blockadeInPerm);

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
Welcome to OStack Knowledge Sharing Community for programmer and developer-Open, Learning and Share
Click Here to Ask a Question

2.1m questions

2.1m answers

60 comments

57.0k users

...