使用char数组编组异常

时间:2012-03-12 07:37:51

标签: c# struct udp marshalling

我在编组脚本方面遇到了一些异常问题。我有C ++结构,我试图模仿C#来测试我们的系统。 C ++结构如下所示:

#pragma pack(1)
typedef struct
{
  ACE_UINT32 result;
  ACE_UINT32 command;
  ACE_TCHAR information[2001];
  ACE_UINT16 informationLength; ///< Length of the variable information.
} MsgStructType;
#pragma pack()

在C#中我声明结构如下:

[StructLayout(LayoutKind.Explicit, Pack = 1)]
struct MsgStruct
{
  [FieldOffset(0)]
  public uint result;
  [FieldOffset(4)]
  public uint command;
  [FieldOffset(8)]
  public Byte[] information;
  [FieldOffset(2009)]
  public ushort informationLength;
}

我使用以下方法序列化和反序列化消息。

public static T DeserializeMsg<T>(Byte[] data) where T : struct
{
  int objsize = Marshal.SizeOf(typeof(T));
  IntPtr buff = Marshal.AllocHGlobal(objsize);

  Marshal.Copy(data, 0, buff, objsize);

  T retStruct = (T)Marshal.PtrToStructure(buff, typeof(T));

  Marshal.FreeHGlobal(buff);

  return retStruct;
}

public static Byte[] SerializeMessage<T>(T msg) where T : struct
{
  int objsize = Marshal.SizeOf(typeof(T));
  Byte[] ret = new Byte[objsize];

  IntPtr buff = Marshal.AllocHGlobal(objsize);

  Marshal.StructureToPtr(msg, buff, true);

  Marshal.Copy(buff, ret, 0, objsize);

  Marshal.FreeHGlobal(buff);

  return ret;
}

我设法序列化邮件,将其发送到udp到收到的同一个应用程序,数据大小似乎是正确的。我得到的问题是当我尝试反序列化消息时。我收到以下错误代码:

Catch exception

使用Byte []的方法可能不完整,但它与我用于序列化和反序列化数据的方法完全相同。唯一不同的是我经历了udp。

一些反复试验使我认识到byte []或char []的定义似乎是个问题。

[StructLayout(LayoutKind.Explicit, Pack = 1)]
struct MsgStruct
{
  [FieldOffset(0)]
  public uint result;
  [FieldOffset(4)]
  public uint command;
  [FieldOffset(8)]
//  public Byte[] information;
//  [FieldOffset(2009)]
  public ushort informationLength;
}

这个系统之间可以毫无问题地进行转移。所以我想我需要处理的字节/字符数组才能声明正确。

2 个答案:

答案 0 :(得分:3)

如果只编写public Byte[] information;,它就会被编组,好像它是一个指向数组的指针,但这不是你在这里所拥有的。你需要做的是指定[MarshalAs(UnmanagedType.ByValArray)],以便它被解释为直接在结构中的数组:

[FieldOffset(8)]
[MarshalAs(UnmanagedType.ByValArray, SizeConst = 2001)]
public byte[] information;

如果你这样做,我认为你不再需要LayoutKind.Explicit了:

[StructLayout(LayoutKind.Sequential, Pack = 1)]
struct MsgStruct
{
    public uint result;
    public uint command;
    [MarshalAs(UnmanagedType.ByValArray, SizeConst = 2001)]
    public byte[] information;
    public ushort informationLength;
}

编辑: information数组必须完全是声明的长度,即使您希望放入少于这么多的字节。因此,使用您的示例,它可能如下所示:

var msg = new MsgStruct();
msg.information = new byte[2001];
var information = Encoding.ASCII.GetBytes("Kalle");
Array.Copy(information, msg.information, information.Length);
var bytes = SerializeMessage(msg);

答案 1 :(得分:1)

  [FieldOffset(8)]
  [MarshalAs(UnmanagedType.ByValArray, SizeConst = 2001)]
  public Byte[] information;