繁体   English   中英

不同应用程序(WPF和Unity)中的C#struct serialization返回不同大小的字节数组

[英]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.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM