C# C中封送处理期间的字节序列问题#
我想用我的笔记本电脑与MES(制造执行系统)通信。 当我序列化数据(结构类型)时,会发生一些事情。 下面的代码是我所做的: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
[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
因此,问题是:
谢谢。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中的某些属性使用小尾端,对其他属性使用大尾端。我会先尝试你的解决方案,如果性能不能满足我的需要,我会尝试直接控制每一点。