C# 封送处理从ushort数组C读取结构#
我正在尝试从字节数组读取结构:C# 封送处理从ushort数组C读取结构#,c#,marshalling,C#,Marshalling,我正在尝试从字节数组读取结构: 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; publ
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, 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();
}
}
如果目的是直接重新解释20个字节的数据,那么它们很可能是你在用艰难的方式做事情;考虑:
使用系统;
使用System.Runtime.InteropServices;
[StructLayout(LayoutKind.Sequential,Pack=1)]
公共结构失败
{
公共卫生服务;
公共部门;
公共部门;
公共卫生服务sh6;
公共卫生服务sh12;
公共封锁;
公共体育事业;
公共体育封锁项目;
}
静态P类
{
静态void Main()
{
var数据=新的ushort[10];
对于(inti=0;i
但是,请注意,重新解释这样的投射是一场终日的噩梦;至少做一些CPU端性断言是值得的(即,如果数据是little endian,如果您的CPU不是,则抛出异常)
如果您没有访问spans的权限,则可以通过safe
获得相同的结果:
故障;
不安全的
{
固定(ushort*ptr=数据)
{//重新解释
故障=*(故障*)ptr;
}
}
//显示数据
Console.WriteLine(failures.cardterr);
Console.WriteLine(failures.TrErr);
Console.WriteLine(failures.KsrErr);
控制台写入线(failures.sh6);
控制台。写入线(失败。sh12);
控制台。写入线(失败。封锁);
Console.WriteLine(failures.biz);
Console.WriteLine(failures.blockadeInPerm);
我很确定你的ChangeUshortToShort
方法并没有达到你的期望:short和ushort都有2个字节,但是ChangeUshortToShort
会将每个ushort变成2个short,也就是说,它会使字节数翻倍“当我做数组()时,它会返回255。”-这到底是什么意思ToArray
返回一个数组-您的意思是255字节吗?或者?@marcGravel它返回数组短[20]和所有值255@canton7这真的没有道理。我被这项任务迷住了。@SilnyToJa我认为你还没有真正定义你要做什么;坦率地说,在这里使用short
/ushort
首先是非常不寻常的:当谈论有效负载时,我们通常处理字节
——但是在大小之间切换是可能的。我认为这是从你问题的第一行开始的:“我试图从字节数组中读取结构:”-当你接下来发布的内容不是字节数组时(在一般情况下,它在内容方面甚至没有很好的定义,除非我们还讨论了endianness),我想测试它,但对MemoryMarshal没有任何用处。这是某种库吗?@SilnyToJa我发布了一篇编辑文章,展示了如何在没有这种库的情况下使用它(改为使用unsafe
),但是:MemoryMarshal
现在是主运行时的一部分-在较旧的框架上,它可能在System.Memory
NuGet包中(但老实说:在撰写本文时,最好只使用最新的.NET版本,即.NET Core 3.1或.NET 5)我不能使用NET 5。最后,当我使用Marshal.StructureToPtr(failures,(IntPtr)ptr,true)时,它似乎可以工作;因为failures=(failures)ptr;throw:@SilnyToJa缺少的一点是,你不能拥有所有bool字段——正如我所说:bool字段是一个八位字节;相反,你需要一个复合字段,然后通过属性对其应用位映射;我已经给出了,它给出了50字节的正确大小(ushort[25]
是50字节).但是!您需要检查位顺序,以确保位按您期望的方式排列,我作弊了,只做了位映射到四个示例结构之一的操作,因此您需要做一些工作。@SilnyToJa这里有一个更简单的方法-使用定义为16位的枚举(:ushort
)。注意:您仍然需要手动检查布局,注意endianness意味着八位字节可能出现交换,因此:您需要非常仔细地检查位是否位于正确的位置(在枚举中-只需更改
[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;
}