gpt4 book ai didi

不同应用程序(WPF 和 Unity)中的 C# 结构序列化返回不同大小的字节数组

转载 作者:行者123 更新时间:2023-11-30 18:14:03 30 4
gpt4 key购买 nike

我有一个 dll,它具有结构定义以及一些用于序列化和反序列化它们的函数。我想将它们放在一个 dll 中,以便可以在不同的应用程序之间共享完全相同的结构。

dll 由 WPF 应用程序(通过 MQTT 发送序列化数据)和 HoloLens 应用程序(使用 Unity 和 VS 开发)共享,后者接收该数据并尝试使用相同的 dll 对其进行反序列化。

问题是当 WPF 应用程序序列化结构时,Marshal.SizeOf(str) 返回大小为 12。而 Unity C# 脚本 app 返回大小为 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 独立应用程序,它以 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 所建议的实际序列化器。

干杯!

关于不同应用程序(WPF 和 Unity)中的 C# 结构序列化返回不同大小的字节数组,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/51399731/

30 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com