我有一个简单的结构:
[StructLayout(LayoutKind.Sequential, Pack = 1, CharSet = CharSet.Auto)]
public struct TestStruct
{
public bool Valid; // 1
public UInt64 Value1; // 8
public UInt64 Value2; // 8
public float Value3; // 4
}
以及这个从字节数组到结构方法的泛型:
public static T ByteArrayToStructure<T>(byte[] bytes) where T : struct
{
var handle = GCHandle.Alloc(bytes, GCHandleType.Pinned);
try
{
return (T) Marshal.PtrToStructure(handle.AddrOfPinnedObject(), typeof(T));
}
finally
{
handle.Free();
}
}
下面是这个简单的单元测试:
[Test]
public void BytesToMyStruct()
{
const bool Valid = true;
const UInt64 Value1 = 1;
const UInt64 Value2 = 2;
const UInt64 Value3 = 99;
var validBytes = BitConverter.GetBytes(Valid);
var value1Bytes = BitConverter.GetBytes(Value1);
var value2Bytes = BitConverter.GetBytes(Value2);
var value3Bytes = BitConverter.GetBytes(Value3);
// 1 + 8 + 8 + 4 = 21
var testBytes = new byte[21];
Array.Copy(validBytes, 0, testBytes, 0, 1);
Array.Copy(value1Bytes, 0, testBytes, 1, 8);
Array.Copy(value2Bytes, 0, testBytes, 9, 8);
Array.Copy(value3Bytes, 0, testBytes, 17, 4);
var myStruct = ByteUtils.ByteArrayToStructure<TestStruct>(testBytes);
Assert.That(myStruct.Valid, Is.EqualTo(true));
Assert.That(myStruct.Value1, Is.EqualTo(1));
Assert.That(myStruct.Value2, Is.EqualTo(2));
Assert.That(myStruct.Value3, Is.EqualTo(99));
}
在这个单元测试中,我只是希望手动填充一个字节数组,反序列化为一个结构,并确保结构的属性等于字节数组中设置的属性。我假设我通过Array.Copy
重复手动复制到相同字节数组的方法失败了,因为当我执行单元测试时,我收到一条失败消息,指出没有正确设置Value1
:
Expected: 1
But was: 0
出于单元测试的目的,我不确定是否通过手动设置字节数组来正确设置它们。
发布于 2019-11-11 22:46:45
根据BOOL
的微软/Windows API定义,System.Boolean
的默认封送处理行为是4字节整数。因此,Marshal.PtrToStructure
假设TestStruct
的非托管表示为24字节,前4个字节由TestStruct.Valid
占用,这会丢弃Value1
和其他字段。
您可以通过对bool
字段应用[MarshalAs(UnmanagedType.I1)]
属性来更改此行为。
https://stackoverflow.com/questions/58808933
复制相似问题