为什么我返回的对象与我收到的对象不匹配?

Why does my returned object not match my received object?

我正在尝试将字节数组反序列化为结构。

这是我的反序列化函数:

void RawDeserialize(byte[] bytearray, object obj)
{
    int len = Marshal.SizeOf(obj);

    IntPtr i = Marshal.AllocHGlobal(len);

    Marshal.Copy(bytearray, 0, i, len);

    obj = Marshal.PtrToStructure(i, obj.GetType());

    Marshal.FreeHGlobal(i);
}

我用

来称呼它
RawDeserialize(outarr, outbuf);

其中 outarr 是长度为 22 的字节数组,outbuf 是我的结构,如下所示:

[StructLayout(LayoutKind.Sequential,Size =22)]
public struct ID_OUTPUT
{
    public HEADER_OUTPUT hdr; //Another struct size=8
    public byte bType;
    public byte bRunning;
    [MarshalAs(UnmanagedType.ByValTStr,SizeConst = 8)]
    public string softwareName; 
    public short softwareVersion;
} 

当我在我的反序列化函数中逐步调试时,obj 填充了正确的值,但是在 return outbuf 填充为零(或者从未分配给因为我最初将所有内容初始化为零)。

我最初的想法是对象没有通过引用传递,但我认为这应该有效,因为我在另一个 SO 问题上发现了这个反序列化函数(我不再有 link 了)。

然后我尝试使用 ref 关键字,但随后出现错误 cannot convert from ref ID_OUTPUT to ref object.

您正在将局部变量 obj 的引用重新定义为不同于您传递给方法的引用。调用方法中的实际引用不会改变。当您将方法签名更改为 ref 变量时,它确实有效,但是您遇到了转换问题。

由于您的方法是 void,最简单的做法是 return 变量并适当地键入它(或在需要时强制转换)。 (你可以在你的 return 变量上使用泛型,任何最适合你的)。

所需的方法签名:

ID_OUTPUT /* your struct return variable */ RawDeserialize(byte[] bytearray);

如果问题仅仅是转换问题,这可以解决问题:

ID_OUTPUT obj;
object outputObject = obj;
RawDeserialize(bytearray, ref outputObject);

obj = (ID_OUTPUT)outputObject;

当您处理多种结构类型并需要一种独特的方法来完成这项工作时,generics 是一个不错的选择。这使您可以使用良好的 C# 语法,而无需将您的实例转换为 object.

// For .Net 4.5 and previous versions
public static T RawDeserialize<T>(byte[] bytearray)
    where T : struct
{
    var type = typeof(T);
    int len = Marshal.SizeOf(type);

    IntPtr i = IntPtr.Zero;
    try
    {
        i = Marshal.AllocHGlobal(len);

        Marshal.Copy(bytearray, 0, i, len);

        return (T)Marshal.PtrToStructure(i, type);
    }
    finally
    {
        if (i != IntPtr.Zero)
        {
            Marshal.FreeHGlobal(i);
        }
    }
}

用法:

ID_OUTPUT myStruct = RawDeserialize<ID_OUTPUT>(someByteArray);
ZZZZ myStruct2 = RawDeserialize<ZZZZ>(someByteArray);

对于 .Net 4.5.1+,您可能需要使用 SizeOf/PtrToStructure 的通用版本:

public static T RawDeserialize<T>(byte[] bytearray)
    where T : struct
{
    int len = Marshal.SizeOf<T>();

    IntPtr i = IntPtr.Zero;
    try
    {
        i = Marshal.AllocHGlobal(len);

        Marshal.Copy(bytearray, 0, i, len);

        return Marshal.PtrToStructure<T>(i);
    }
    finally
    {
        if (i != IntPtr.Zero)
        {
            Marshal.FreeHGlobal(i);
        }
    }
}