C# 将非常量大小的结构转换为字节数组
我正在开发一个库,它通过C# 将非常量大小的结构转换为字节数组,c#,arrays,struct,marshalling,data-conversion,C#,Arrays,Struct,Marshalling,Data Conversion,我正在开发一个库,它通过UDP消息与µ控制器通信。为此,我使用了一个自定义协议,它基本上是一个由两个元素组成的结构:头(一些元数据+校验和)和负载。 通信通过System.Net.Sockets.UDPClient类完成。要转换数据,我使用以下函数: private List<byte> GetBytes(object str) { int size = Marshal.SizeOf(str); byte[] arr = new byte[size]; Int
UDP消息与µ控制器
通信。为此,我使用了一个自定义协议,它基本上是一个由两个元素组成的结构:头(一些元数据+校验和)和负载。
通信通过System.Net.Sockets.UDPClient
类完成。要转换数据,我使用以下函数:
private List<byte> GetBytes(object str)
{
int size = Marshal.SizeOf(str);
byte[] arr = new byte[size];
IntPtr ptr = Marshal.AllocHGlobal(size);
Marshal.StructureToPtr(str, ptr, true);
Marshal.Copy(ptr, arr, 0, size);
Marshal.FreeHGlobal(ptr);
return arr.ToList();
}
在您的外围协议
示例中,您实际上并没有将数据放入结构中,而是创建一个单独的数组并将数据放入其中。当然,您仍然可以这样做,但您必须支付大量的管理费用。在这种情况下,忘记Marshal
——您只需将arr
传递给结构
但如果你的意思是“我可以在.NET中拥有可变长度的结构吗”;否-不可以。在您的外围协议
示例中,您实际上并没有将数据放入结构中,而是创建一个单独的数组并将数据放入其中。当然,您仍然可以这样做,但您必须支付大量的管理费用。在这种情况下,忘记Marshal
——您只需将arr
传递给结构
但如果你的意思是“我可以在.NET中拥有可变长度的结构吗”;否-不可以。为什么要使用结构
使用一个类。此示例代码允许您添加新的数据包类型并将其转换为字节。如果您想要将其转换回(从字节到类)的机制,则需要添加您自己的发明
public abstract class Packet
{
public int PacketType { get; }
public Packet (int packetType)
{
PacketType = packetType;
}
protected abstract byte[] GetPayload ();
private int CalculateChecksum ()
{
byte[] packetTypeBytes = BitConverter.GetBytes (PacketType);
byte[] payloadBytes = GetPayload ();
byte[] lengthBytes = BitConverter.GetBytes (payloadBytes.Length);
return 0; // add some logic to calculate checksum from all bytes
}
public byte[] ToBytes ()
{
byte[] packetTypeBytes = BitConverter.GetBytes (PacketType);
byte[] checksumBytes = BitConverter.GetBytes (CalculateChecksum ());
byte[] payloadBytes = GetPayload ();
byte[] lengthBytes = BitConverter.GetBytes (payloadBytes.Length);
return packetTypeBytes.Concat (lengthBytes).Concat (checksumBytes).Concat (payloadBytes).ToArray ();
}
}
public sealed class ActionA : Packet
{
public string Message { get; }
public ActionA (string message) : base (0)
{
Message = message;
}
protected override byte[] GetPayload ()
{
return Encoding.ASCII.GetBytes (Message);
}
}
public sealed class ActionB : Packet
{
public int Value { get; }
public ActionB (int value) : base (1)
{
Value = value;
}
protected override byte[] GetPayload ()
{
return BitConverter.GetBytes (Value);
}
}
为什么要使用结构
使用一个类。此示例代码允许您添加新的数据包类型并将其转换为字节。如果您想要将其转换回(从字节到类)的机制,则需要添加您自己的发明
public abstract class Packet
{
public int PacketType { get; }
public Packet (int packetType)
{
PacketType = packetType;
}
protected abstract byte[] GetPayload ();
private int CalculateChecksum ()
{
byte[] packetTypeBytes = BitConverter.GetBytes (PacketType);
byte[] payloadBytes = GetPayload ();
byte[] lengthBytes = BitConverter.GetBytes (payloadBytes.Length);
return 0; // add some logic to calculate checksum from all bytes
}
public byte[] ToBytes ()
{
byte[] packetTypeBytes = BitConverter.GetBytes (PacketType);
byte[] checksumBytes = BitConverter.GetBytes (CalculateChecksum ());
byte[] payloadBytes = GetPayload ();
byte[] lengthBytes = BitConverter.GetBytes (payloadBytes.Length);
return packetTypeBytes.Concat (lengthBytes).Concat (checksumBytes).Concat (payloadBytes).ToArray ();
}
}
public sealed class ActionA : Packet
{
public string Message { get; }
public ActionA (string message) : base (0)
{
Message = message;
}
protected override byte[] GetPayload ()
{
return Encoding.ASCII.GetBytes (Message);
}
}
public sealed class ActionB : Packet
{
public int Value { get; }
public ActionB (int value) : base (1)
{
Value = value;
}
protected override byte[] GetPayload ()
{
return BitConverter.GetBytes (Value);
}
}
@killerisded的可能重复我认为这并不能解决问题的关键部分请注意,在您的代码中,您正在分配一些非托管内存,对其进行写入,然后释放非托管内存-这。。。实际上对@KillerIsDead的任何可能的副本都不是很有用。我认为这并不能解决问题的关键部分。请注意,在您的代码中,您正在分配一些非托管内存,对其进行写入,然后释放非托管内存-即。。。实际上对任何东西都不是很有用在µController上运行的C代码使用结构。我只是把它们复制并改编成我的C#library@kain:忘记控制器端的C代码。只需发送有效数据。如果使用C#,则程序类似于C#,而不是C。在µ控制器上运行的C代码使用结构。我只是把它们复制并改编成我的C#library@kain:忘记控制器端的C代码。只需发送有效数据。如果您使用C#,则程序类似于C#,而不是C。