Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/csharp/267.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中封送处理期间的字节序列问题#_C#_Serialization_Marshalling - Fatal编程技术网

C# C中封送处理期间的字节序列问题#

C# C中封送处理期间的字节序列问题#,c#,serialization,marshalling,C#,Serialization,Marshalling,我想用我的笔记本电脑与MES(制造执行系统)通信。 当我序列化数据(结构类型)时,会发生一些事情。 下面的代码是我所做的: [StructLayout(LayoutKind.Sequential, Pack = 4)] struct DataPackage { public int a; public ushort b; public byte c; [MarshalAs(UnmanagedType.ByValTStr, SizeConst = 5)] publi

我想用我的笔记本电脑与MES(制造执行系统)通信。 当我序列化数据(结构类型)时,会发生一些事情。 下面的代码是我所做的:

[StructLayout(LayoutKind.Sequential, Pack = 4)]
struct DataPackage
{
    public int a;
    public ushort b;
    public byte c;
    [MarshalAs(UnmanagedType.ByValTStr, SizeConst = 5)] public string d;
}
class Program
{
    static void Main(string[] args)
    {
        DataPackage pack1 = new DataPackage();
        pack1.a = 0x33333301;
        pack1.b = 200;
        pack1.c = 21;
        pack1.d = "hello";
        byte[] pack1_serialized = getBytes(pack1);
        Console.WriteLine(BitConverter.ToString(pack1_serialized));


        byte[] getBytes(DataPackage 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;
        }
    }
}
结果如下:

我希望结果是这样的:

 static int ToBigEndianInt(int x) {
    if (!BitConverter.IsLittleEndian)
        return x; // already fine
    var ar = BitConverter.GetBytes(x);
    Array.Reverse(ar);
    return BitConverter.ToInt32(ar, 0);
 }

static ushort ToBigEndianShort(ushort x) {
    if (!BitConverter.IsLittleEndian)
        return x; // already fine
    var ar = BitConverter.GetBytes(x);
    Array.Reverse(ar);
    return BitConverter.ToUInt16(ar, 0);
}
33-33-33-01-00-C8-15-68-65-6C-6C-6F

因此,问题是:

  • 为什么编组后,uint/ushort类型数据是反向的
  • 有没有其他方法可以按我想要的顺序发送数据
  • 为什么字符串“hello”中的最后一个单词“o”会在字节数组中消失

  • 谢谢。

    1-因为您的预期结果是big-endian,而您的系统似乎使用little-endian,所以与您预期的字节顺序基本相反

    2-最简单的方法是在编组之前将数字“转换”为大端(也就是说,在使用小端进行转换时,以一种能够产生所需结果的方式进行更改),例如:

     static int ToBigEndianInt(int x) {
        if (!BitConverter.IsLittleEndian)
            return x; // already fine
        var ar = BitConverter.GetBytes(x);
        Array.Reverse(ar);
        return BitConverter.ToInt32(ar, 0);
     }
    
    static ushort ToBigEndianShort(ushort x) {
        if (!BitConverter.IsLittleEndian)
            return x; // already fine
        var ar = BitConverter.GetBytes(x);
        Array.Reverse(ar);
        return BitConverter.ToUInt16(ar, 0);
    }
    
    然后:

    pack1.a = ToBigEndianInt(0x33333301);
    pack1.b = ToBigEndianShort(200);
    
    请注意,这种转换方式效率不高,如果需要更高的性能,可以通过一些位操作来实现


    3-因为字符串以null结尾,并且此null终止符在
    SizeConst
    中计数。因为您有5个字符,所以字符串将有4个字符+1个空终止符。只需增加
    SizeConst=6
    (由于
    Pack=4
    ,这可能会在末尾添加额外的零)。

    您的机器是little endian。SizeConst=5不足以存储“hello”。谢谢,非常有用!我发现我要与之通信的MES对struct中的某些属性使用小尾端,对其他属性使用大尾端。我会先尝试你的解决方案,如果性能不能满足我的需要,我会尝试直接控制每一点。