问题描述
我正在尝试从字节数组中读取结构:
var data = new ushort[10]{65535,65535,65535 ...};
var datashort = ChangeUshortToShort(data);
FromArray(datashort )
还有我的结构:
[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,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(),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();
}
}
方法 ChangeUshortToShort 返回所有值为 255 的数组。
当我执行 ToArray() 时返回 255。但是如果我执行 FromArray() 它会在应该 65535 时为 ushort 分配 255 值。并在应该是 4294967295 时为 uint 分配 16711935。
我认为我应该使用 MarshalAs 属性,但不知道如何使用。有人可以帮我吗?
编辑:
第二种结构:
[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;
}
解决方法
如果打算直接重新解释 20 字节的数据,他们可能做事很困难;考虑:
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);
}
}
但是请注意,像这样重新解释强制转换是字节序的噩梦;值得做出一些 CPU 端序断言,至少(即,如果数据是小端序的,如果您的 CPU 不是,则抛出异常) >
如果您无法访问跨度,则可以通过 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);