我在编组脚本方面遇到了一些异常问题。我有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到收到的同一个应用程序,数据大小似乎是正确的。我得到的问题是当我尝试反序列化消息时。我收到以下错误代码:
使用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;
}
这个系统之间可以毫无问题地进行转移。所以我想我需要处理的字节/字符数组才能声明正确。
答案 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;