2012-03-01 23 views
2

私は、構造体のJPINfoへのポインタをとるDLLにC++関数を持っています。この関数はサーバから受け取ったデータで満たされています。以下に見られる:C#の構造体へのポインタをC++ DLLに送信する

typedef struct JP 
{ 
    unsigned char type; 
    DWORD value; 
} JP; 

typedef struct JPInfo 
{ 
    JP jps[3]; 
    _int16 ConT; 
    _int16 CallT; 
    unsigned char ret; 
    unsigned char count; 
    unsigned char JPOffset; 
    unsigned char JPPeriod; 
} JPInfo; 

機能がそうようDLLにエクスポートされる:

__declspec(dllexport) DWORD __stdcall GetJPInfo(JPInfo* jpi, DWORD time); 

関数はJPInfo構造体へのポインタを取るを、IはC#で、この構造体を模倣することを試みた

私はタイプ「System.ExecutionEngineException」の未処理の例外を取得

[DllImport("DLLImp.dll")] 
    unsafe public static extern int GetJP(ref JPInfo jpi, int time); 
// then in main... 
JPInfo jpi = new JPInfo; 
GetJackpotValues(ref jpi, 4000); 

:3210

私はそうのようなC#のから関数を呼び出すを試みます。私はJPInfo構造体にJP構造体の固定サイズの配列を持つことができないので、これにどのようにアプローチするのか分かりません。

ありがとうございました。

+0

sieを明示的に指定しないでください。デフォルトのMarshallerはそれを実行します。 (サイズ= 23,5など) – Digvijay

答えて

2

は、C++の構造体がパックされていると仮定すると、あなたのC#の構造体は次のようになります。

[StructLayout(LayoutKind.Sequential, Pack=1)] 
public struct JP 
{ 
    byte type; 
    uint value; 
} 

[StructLayout(LayoutKind.Sequential, Pack=1)] 
public struct JPInfo 
{ 
    [MarshalAs(UnmanagedType.ByValArray, SizeConst=3)] 
    JP[] jps; 
    Int16 ConT; 
    Int16 CallT; 
    byte ret; 
    byte count; 
    byte JPOffset; 
    byte JPPeriod; 
} 

一方、彼らはパックされていない場合、 StructLayout属性のPackパラメータを削除します。 C++ヘッダーファイルの#pragma packステートメントを調べて、C++構造体がパックされているかどうかを調べる必要があります。

私は、C++構造体がパックされていると推測しています。なぜなら、それらがサーバーから受け取ったデータにマップされているからです。

あなたのインポートがそうのようにする必要があります:

[DllImport("DLLImp.dll")] 
public static extern uint GetJP(ref JPInfo jpi, uint time); 

DWORDuintではなくintに変換し、ここでは、安全でないコードは必要ありません。

+0

絶対完璧! Davidに感謝します。 –

4

構造体のSize属性を削除しようとしましたか?私は同様のことをするときにサイズを指定する必要はありませんでした。お使いのアレイのプロパティのために、彼らが好き帰属してみてください:

[StructLayout(LayoutKind.Sequential)] 
public struct JPInfo 
{ 
    [MarshalAs(UnmanagedType.ByValArray, SizeConst = 3)] 
    JP[] jps; 
    Int16 ConT; 
    Int16 CallT; 
    byte ret; 
    byte count; 
    byte JPOffset; 
    byte JPPeriod; 
} 
+0

今はエラーが出ていませんが、構造体の項目の順序が重要であるため、DLLでバイト・コピーのダイレクト・バイトが実行されているため、私は構造体のメンバーがメモリ内の同じ順番になることを構造体宣言した方法を行いますか? –

+0

はい、これは行く方法です。また、作成時に 'JP [] jps = new JP [3];'という配列を初期化します。 – Krizz

+0

LayoutKind.Sequentialを指定すると、.NETアプリケーションで構造体プロパティを定義した順序でメモリがレイアウトされます。動的な配列サイズを持つことは、パイプ全体に正確なメモリ割り当てを送信する必要があるため、私にとって意味をなさないでしょう。 –

関連する問題