Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/csharp/310.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181

Warning: file_get_contents(/data/phpspider/zhask/data//catemap/6/google-chrome/4.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C# 将非常量大小的结构转换为字节数组_C#_Arrays_Struct_Marshalling_Data Conversion - Fatal编程技术网

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。