Marshal从一个短数组中读取一个结构



我正在尝试从字节数组读取结构:

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

And my structure:

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

方法ChangeUshortToShort返回所有值为255的数组。

当我做ToArray()它返回255。但是如果我执行frommarray(),它会为ushort分配255个值,而应该是65535。并将应该为4294967295的int赋值为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不是,则抛出异常)

如果不能访问span,可以通过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);

最新更新