[英]C# struct serialization in different applications (WPF and Unity) returns byte array of different sizes
我有一个结构定义的dll,也很少有序列化和反序列化的函数。 我想把它们放在一个dll中,这样就可以在不同的应用程序之间共享完全相同的结构。
该DLL由WPF应用程序(通过MQTT发送序列化数据)和HoloLens应用程序(使用Unity和VS开发)共享,该应用程序接收该数据并尝试使用相同的dll对其进行反序列化。
问题是,当WPF应用程序序列化结构时,Marshal.SizeOf(str)返回12的大小。而Unity C#scripts应用程序中完全相同的dll函数返回24的大小。此外,最后12个字节在数组都是0。
因此,在尝试反序列化来自WPF应用程序的对象时,存在超出范围的异常,因为它们是Unity脚本中预期大小的一半。
这是我序列化的结构的一个例子:
[Serializable]
public struct SimulationVariableModel
{
public string Name { get; set; }
public string Category { get; set; }
public string ObjectId { get; set; }
}
以下是将Struct序列化为字节数组的函数:
public static byte[] StrucToByteArray<T>(T str) where T : struct
{
// In Unity: size = 24
// In standalone WPF and UWP application: size = 12
int size = Marshal.SizeOf(str);
byte[] arr = new byte[size];
IntPtr ptr = Marshal.AllocHGlobal(size);
try
{
Marshal.StructureToPtr(str, ptr, false);
Marshal.Copy(ptr, arr, 0, size);
}
finally
{
Marshal.FreeHGlobal(ptr);
}
return arr;
}
以及将字节数组转换为原始结构的函数:
public static T ByteArrayToStruct<T>(byte[] arr) where T : struct
{
T str = default;
int size = Marshal.SizeOf(str);
IntPtr ptr = Marshal.AllocHGlobal(size);
try
{
Marshal.Copy(arr, 0, ptr, size);
str = (T)Marshal.PtrToStructure(ptr, str.GetType());
} finally
{
Marshal.FreeHGlobal(ptr);
}
return str;
}
这是在Unity中接收序列化数据并尝试将其反序列化为原始结构的事件处理程序:
private void Client_MqttMsgPublishReceived(object sender, MqttMsgPublishEventArgs e)
{
if (e.Topic == NewSimulationVariableTopic) {
// Dummy item to test that the byte Array length is not due to extra data in e.Message.
SimulationVariableModel test = new SimulationVariableModel { Name = "Bla", Category = "Bla" };
// testByteArray.Length = 24
byte[] testByteArray = StrucToByteArray(test);
// De-serialization is successful
test = ByteArrayToStruct<SimulationVariableModel>(testByteArray);
// e.Message is the result from serialization
// using StructToByteArray<SimulationVariableModel>(str) in standalone WPF and UWP app.
// De -serialization fails because e.Message.Length = 12
SimulationVariableModel simVar = ByteArrayToStruct<SimulationVariableModel>(e.Message);
// Logic with SimulationVariableModel
}
}
我想这可能是由Unity环境造成的? 我测试了一个UWP独立应用程序,它将Structs序列化为12个字节而不是24个字节。
有没有人知道可能发生的事情以及如何解决这个问题?
非常感谢。
正如一些评论所暗示的那样,两个平台中的字符串处理方式不同。 我通过指定结构在其定义中如何序列化来解决这个特定问题。 例:
[Serializable]
[StructLayout(LayoutKind.Sequential, CharSet = CharSet.Ansi, Pack = 1)]
public struct SimulationVariableModel
{
[MarshalAs(UnmanagedType.ByValTStr, SizeConst = 256)]
public readonly string Name;
[MarshalAs(UnmanagedType.ByValTStr, SizeConst = 256)]
public readonly string Category;
[MarshalAs(UnmanagedType.ByValTStr, SizeConst = 256)]
public readonly string Id;
public SimulationVariableModel(string name, string category, string objectId)
{
Name = name;
Category = category;
Id = objectId;
}
}
但是,对于更强大的解决方案,我可能最好使用Mark Gravell和bassfader建议的实际串行器。
干杯!
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.