2009-07-27 9 views
2

カードリーダーとやりとりするC++ DLLがあります。データ構造体へのポインタが必要ですが、これは問題ありません。しかし、C#でDLLと対話しようとすると、私はあらゆる種類の問題を抱えています。保護されたメモリへの書き込みエラー、getDataコマンドの実行後にシャットダウンしたアプリケーションなどマーシャリングの問題

ヘッダ

void readCard(cardData* dataBuffer); 

C#コードから

C++方法IもMarshal.StructureToPtrを使用してのIntPtrとしてcardDataを通過しようとした

Wrapper.cs 
public struct cardData{ 
    Byte[] data01; 
    Byte[] data02; 
} 

[dllImport("card.dll")] 
public static extern void readCard(ref cardData data); 

のForm1.cs

Wrapper.cardData tmpData = new wrapper.cardData(); 
tmpData.data01 = new Byte[]; 
tmpData.data02 = new Byte[]; 
readCard(ref tmpData); 

、その返されたときにptrを構造体Marshal.PtrToStructureに読み込もうとしたときにデータを返さなかった...

多くの人々がC/C++ DLLを使って作業しようとしているようだから、ヘルプファイルやその他の投稿を使ってこれを解決しようとしています。私はC++ですべてのことを書こうとしていて、C++ DLLで解析されたデータで文字列を返すようにしようとしましたが、保護されたメモリエラーに読み書きをスローします。

+0

構造体のC++定義を表示できますか?私はマッピングに何か間違っていると思います... –

答えて

0

cardDataはStructLayoutAttributeを使用する必要があります。また、Dependency Walkerを使用して、そのメソッドのcard.dll内の場所を探し、それを名前付きパラメーターとして追加できます。

0

あなたのバイト[]にはサイズが関連付けられていないことに気付きました。配列の大きさを知っていますか? IIRCでは、初期化時に配列の領域を割り当てる必要があります。

私が拠点を離れている場合はお知らせください。この投稿を削除します。

0

PInvoke Signature Toolkitはこれまで私を助けてくれました。

たとえば、次のC/C++:

struct cardData{ 
byte[] data01; 
byte[] data02; 
} 

void readCard(cardData* dataBuffer); 

は、それはあります

System.Runtime.InteropServices.StructLayoutAttribute( System.Runtime.InteropServices.LayoutKind.Sequential)] 
public struct cardData { 

    /// byte[] 
    public byte[] data01; 

    /// byte[] 
    public byte[] data02; 
} 

/// Return Type: cardData 
///dataBuffer: cardData* 
public delegate cardData readCard(ref cardData dataBuffer); 
1

私はあなたのコードを参照の最大の問題は、あなたのバイト[]メンバーは、明示的与えられていないということですサイズ。このサイズの演算子がなければ、マーシャルは単純な参照型のように扱います。結果として生じる構造体は、32ビットプラットフォーム上で8バイトのサイズを持ち、保護されたメモリの書き込みにほぼ確実につながります。

バイト配列がCコードの固定サイズであると仮定すると、MarshalAs属性を使用して、バイト配列にマネージコードと同じセマンティクスを与える必要があります。これは彼らに固定サイズを与えることを必要とする。

[StructLayout(LayoutKind.Sequential)] 
public struct cardData{ 
    [MarshalAs(UnmanagedType.ByValArray, SizeConst=300)] 
    Byte[] data01; 
    [MarshalAs(UnmanagedType.ByValArray, SizeConst=300)] 
    Byte[] data02; 
} 

300を、アレイのネイティブコードで指定されたサイズに変更します。

また、StructLayout属性も追加する必要があります。

0

私が作ったC#のC-DLLラッパーのスニペットです。

Yuriyと同じように、StructLayout属性が不足しています。おそらく、構造体と関数宣言でネイティブ型を使用しているはずです。これはおそらくあなたが受け入れるかもしれないかもしれないが、いくつかの場所でunsafeキーワードを使用する必要があります - それは私にとっては良かったです。

[StructLayout(LayoutKind.Sequential)] 
public unsafe struct X_Message 
{ 
     public byte id; 
     public byte* data; 
     public DWORD data_length; 
} 

// ... 

[DllImport("x-driver.dll")] 
protected unsafe static extern int X_ReadMessage(void* h, X_Message* message); 
-1

バイト[]の代わりにIntPtrを使用してください。 DLLが管理対象データを処理できません。

0

したがって、構造体は構造体レイアウトで示唆されているように設定されています。

Wrapper.cs

[StructLayout(LayoutKind.Sequential)] 
public struct cardData{ 
    [MarshalAs(UnmanagedType.ByValArray, SizeConst=99)] 
    Byte[] data01; 
    [MarshalAs(UnmanagedType.ByValArray, SizeConst=101)] 
    Byte[] data02; 
} 

[DllImport("card.Dll")] 
public static extern void readCard(ref cardData data); 

そして今、それだけで...何のエラー、データに変化が閉じていない、アプリはちょうどシャットダウンします。

関連する問題