2012-03-12 40 views
1

編組腳本發出異常時出現了一些問題。我有C++結構,我嘗試在C#中模擬測試我們擁有的系統。的C++結構看起來像這樣:與char數組的編組異常

#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

也許方法使用字節[]是不完整的,但它是我使用的serializeing和unserializeing數據完全相同的類。唯一的區別是我經歷了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; 
} 

這一個可以在系統之間轉移沒有問題。所以我猜它是我需要用來聲明正確的byte/char數組。

+1

什麼是ACE_TCHAR? – 2012-03-12 09:16:09

+0

對不起,它來自ACE框架, typedef uint32_t ACE_UINT32; typedef char ACE_TCHAR; typedef uint16_t ACE_UINT16 – Andreas 2012-03-12 10:07:51

+0

我的C++已經過時了,你是否在C++中檢查'sizeof(char)== 1'? – 2012-03-12 10:33:04

回答

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); 
+0

嗯,嘗試這將使serializemessage在行_Marshal.StructureToPtr(msg,buff,true)上拋出一個無法識別的結構異常; _ – Andreas 2012-03-13 05:47:52

+0

它不會丟給我。我不知道可能是什麼問題。 – svick 2012-03-13 09:14:07

+0

如何將數據分配給信息表?我使用_struct.information = Encoding.ASCII.GetBytes(「Kalle」); _當我嘗試。 – Andreas 2012-03-13 12:03:59

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

只是一段代碼不是很有用。下一次,您可能想要包含一些信息,說明它爲什麼需要它以及它做了什麼。 – svick 2012-03-12 13:21:37