2011-07-20 6 views
4

C#で書かれたアプリケーションがあり、Cで書かれたDLLが使用されています。 一部のデリゲート(関数ポインタ)を通じて、私はC関数を呼び出すことができました。この関数は、一部のデータに対して多くの処理を行い、処理されたバイナリデータをデータのサイズとともにC#コードに戻すことが期待されています。アンマネージドコード(C)からマネージコード(C#)にデータを渡します。

private unsafe delegate void MyCallback (IntPtr cs_buf, Int32 cs_size);

そして、私のように私のC codeからこれを呼び出しています:

管理c#関数のプロトタイプは、管理C#コードで

void* c_buf = NULL; 
int c_size = 0; 

.... some processing here to fill buf and size...... 

MyCallback (c_buf, c_size); 

、私は、関数を呼び出す必要がありますプロトタイプを持つMyCallbackから:

void foo (byte[] cs_buf, int cs_size)

cs_size値に問題はないが、それはC#コードでbyte[]として使用することができるように、CコードからC#コードをバイナリバッファを通過/使用する正しい方法は何です。

私がしていることが正しい方法であれば、受信したIntPtr cs_bufbyte[]に変換する推奨方法は何ですか?

おかげで、 ビクラム

答えて

2

あなたが管理し、8ビット 符号なし整数配列にアンマネージメモリポインタからMarshal.Copy

Marshal.Copy Method (IntPtr, Byte[], Int32, Int32)

コピーデータを使用する必要があります。この場合foo()は、それが配列の代わりに.Lengthプロパティを使用することができますようcs_sizeパラメータを取る必要はありません道int型によって

var array = new byte[cs_size]; 
Marshal.Copy(pointer, array, 0, cs_size); 
foo(array, cs_size); 

cs_sizeはバイト単位のサイズであると仮定すると

。これでまた


、C#のコードは、配列をコピーして、あなただけのコールバックを呼び出した後にCコードからバッファを free()ことができます。

そうでない場合は、Windowsの下でCからmylib_free()方法をエクスポートするか、(C#のから)LocalAlloc(Cから)とMarshal.FreeHGlobalのように知られているメモリアロケータ(NOT malloc)を使用するのいずれかが必要になります。

+0

プロジェクトにマネージC++コードがなく、これがこの1回の呼び出しである場合は、これが最適なソリューションです。 –

+0

+1。それはうまくいった。ありがとう:)しかし、私はちょうど考えていた、これは余分なコピーオーバーヘッドを導入していないのですか? –

+0

これはありますが、管理されたC++がなく、そのような呼び出しが多くなく、パフォーマンスがそれほど重要ではない場合は、依然として最良のソリューションです。私の答えは余分なコピーを避けるために使うことができますが、ドットネットアセンブリにコンパイルできるC++プロジェクトを作る必要があります。 –

4

これはMicrosoftがC++/CLI用に作ったものです(Managed C++とも呼ばれます)。

void call_foo(array<Byte>^ bytes) 
{ 
    pin_ptr<Byte> ptrBuffer = &bytes[bytes->GetLowerBound(0)]; 
    foo(ptrBuffer, bytes->Length); 
} 

これは、バイトのC#の配列を取るそのメモリを固定して、その長さで、fooへのバイトのCスタイルの配列として渡します:あなたはこのような関数を書くことができます。クリーンアップや何かを解放する必要はありません。 call_fooの終了時にスコープの外に出ると、固定ポインタは自動的に固定解除されます。清潔でシンプル。

関連する問題