为什么我返回的对象与我收到的对象不匹配?
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);
}
}
}
我正在尝试将字节数组反序列化为结构。
这是我的反序列化函数:
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);
}
}
}