2012-03-12 16 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() 

[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; 
} 

私はメッセージをシリアライズし、デシリアライズするには、次の方法を使用してC++の構造体は次のようになります。

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; 
} 

これはシステム間で問題なく転送できます。だから私は正しいと宣言するために必要なバイト/文字配列を推測する。

+1

「ACE_TCHAR」とは何ですか? –

+0

申し訳ありませんが、それはACEフレームワークのものです typedef uint32_t ACE_UINT32; typedef char ACE_TCHAR; typedef uint16_t ACE_UINT16 – Andreas

+0

私のC++は古くなっていますが、C++で 'sizeof(char)== 1'をチェックしましたか? –

答えて

3

あなただけpublic Byte[] information;を記述する場合、それが配列へのポインタであるかのようにマーシャリングが、それはあなたがここに持っているものではありませんです。

[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; 
} 
それは構造体に直接だ配列として解釈されますように、何をする必要がある、 [MarshalAs(UnmanagedType.ByValArray)]を指定することです

EDIT: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

これを試してみると、_Marshal.StructureToPtr(msg、buff、true); _ – Andreas

+0

という行で、serializemessageが認識できない構造体例外をスローします。私は何が問題になるか分かりません。 – svick

+0

情報テーブルにどのようにデータを割り当てますか?私は_struct.information = Encoding.ASCII.GetBytes( "Kalle"); _を使用しました。 – Andreas

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

コードのほんの一部はあまり役に立ちません。次回は、なぜ必要なのか、何が必要なのかについての情報を含めることができます。 – svick