简体   繁体   English

Marshal 从 ushort 数组 C# 读取结构

[英]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.方法 ChangeUshortToShort 返回所有值为 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.当我执行 ToArray() 时,它返回 255。但如果我执行 FromArray(),它会在 65535 时为 ushort 分配 255 值。并在 4294967295 时为 uint 分配 16711935。

I think i should use attributes MarshalAs, but dont know how.我想我应该使用属性 MarshalAs,但不知道如何。 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;
}

If the intention is to re-interpret the 20 bytes of data directly, they you're probably doing things the hard way;如果打算直接重新解释这 20 个字节的数据,那么您可能正在以艰难的方式做事; 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 (ie if the data is little-endian, throw an exception if your CPU isn't )至少做一些 CPU-endianness 断言是值得的(即,如果数据是 little-endian,如果您的 CPU不是,则抛出异常)

If you don't have access to spans, the same result can be achieved via unsafe :如果您无权访问跨度,则可以通过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);

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM