2011-01-03 21 views
1

私はアプリケーションをC++からC#に変換しており、構造体の読み込みを処理する適切な方法について質問があります。私が使用したときに、私はCのC#にCのDLLから構造体を構造体に変換しようとしています。これdllからCへC構造体を変換するにはどうすればいいですか?

typedef struct card_info 
{ 
    ushort r; 
    ushort s; 
    enum_a a; 
    usinged long ul; 
    ushort n; 
    ushort* b; 
    ushort id; 
} CARD_INFO; 

のように見えます[StructLayout(LayoutKind.Sequentaial)]は、配列のサイズは、C#で20バイトです。しかし、私のC++コードを見てみると24バイトです。私はこのように私のC#を変更:

[StructLayout(LayoutKind.Explicit)] 
public struct CardInfo 
{ 
    [FieldOffset(0) public ushort r; 
    [FieldOffset(2) public ushort s; 
    [FieldOffset(4) public EnumA a; 
    [FieldOffset(8) public ushort ul; 
    [FieldOffset(12) public ushort n; 
    [FieldOffset(16) public UInt32 b; 
    [FieldOffset(20) public ushort id; 
} 

これはコンパイルするようだが、私は、これはこれを行うについては移動するための正しい方法である確信していません。これが正しかったか、よりよい方法があるかどうか私に教えてください。

おかげ

答えて

4
usinged long ul; 

それはタイプミスだが、それは間違いUSHORTではない、それはUINTです。

FieldOffsetを使用しないでください。コンパイラーはそれを把握してください。今度はMarshal.SizeOf()が24を返し、適切な量のパディングが挿入されます。 bメンバーはIntPtr btwである必要があります。

0

ulは、C実装のunsigned longですが、unsigned shortを使用しています。なぜあなたのStructLayout.Sequentialの実装が小さすぎるのか不思議であれば、これは良いスタート地点になります。

EnumAの実装を再度確認して、正しいサイズであることを確認してください。

1

@ 答えが正しいですが、マーシャルされたデータのデバッグに関するヒントを追加して、結果を確認することができます。私は構造体をインスタンス化し、このようなポインタを作成します。

CardInfo cardInfo = new CardInfo(); 
IntPtr pointer = Marshal.AllocHGlobal(Marshal.SizeOf(cardInfo)); 
Marshal.StructureToPtr(cardInfo, pointer, false); 

ブレークポイントを最後の行に貼り付け、ブレークポイントまでデバッガにステップインします。地元/自動車のウィンドウにはpointerが表示されています。値はint値でなければなりません。 (ここでは16進表示が最適です)。 dc 0x0086bf30 <

Img1

コマンドウィンドウに上に移動し、入力 - あなたのポインタのアドレス。メモリ内のデータをダンプする必要があります。 dcと入力すると、次のチャンクがダンプされます。また、dadbdddfdqを使用して、異なる種類のデータをダンプすることもできます。次のブレークポイント(F10)をステップ実行し、同じメモリを再度ダンプしてください。

Img2

あなたは、特定の値を使用して構造体のフィールドを初期化し、それが必要として働いているかどうかを確認するために、ここで変化を観察することができます。

関連する問題