29

IntPtr ポインターからバイト配列にデータを取得したいと考えています。次のコードを使用してそれを行うことができます。

IntPtr intPtr = GetBuff();
byte[] b = new byte[length];
Marshal.Copy(intPtr, b, 0, length);

しかし、上記のコードは、IntPtr からバイト配列へのコピー操作を強制します。問題のデータが大きい場合、これは適切なソリューションではありません。

IntPtr をバイト配列にキャストする方法はありますか? たとえば、次のように動作します。

byte[] b = (byte[])intPtr

これにより、コピー操作が不要になります。

また、IntPtr が指すデータの長さをどのように判断できますか?

4

4 に答える 4

23

他の人が述べたように、コピーせずにマネージド にデータを保存する方法はありませんbyte[](提供した現在の構造*)。ただし、実際にマネージ バッファーに格納する必要がない場合は、操作を使用unsafeして、アンマネージ メモリを直接操作できます。それは本当にあなたがそれをどうする必要があるかによって異なります。

すべてbyte[]の参照型とその他の参照型は CLR ガベージ コレクターによって管理され、使用されなくなったときにメモリの割り当てと解放を行うのはこれです。の戻り値が指すメモリGetBufferは、C++ コードによって割り当てられたアンマネージド メモリのブロックであり、(メモリ レイアウト/実装の詳細は別として) GC マネージド メモリとは本質的に完全に分離されています。したがって、GC マネージド CLR 型 ( byte[]) を使用して、 が指すアンマネージド メモリ内に現在保持されているすべてのデータを含める場合はIntPtr、GC が認識しているメモリにデータを移動 (コピー) する必要があります。これは、コードや pinvoke などMarshal.Copyを使用したカスタム メソッドによって、またはカスタム メソッドによって行うことができます。unsafe

ただし、それをどうしたいかによって異なります。あなたはそれがビデオデータだと言いました。データに何らかの変換またはフィルターを適用する場合は、おそらくアンマネージ バッファーで直接行うことができます。バッファーをディスクに保存したい場合は、おそらくアンマネージ バッファーで直接行うことができます。

長さについては、アンマネージ メモリ バッファーの長さを知る方法はありません。ただし、バッファーを割り当てた関数が長さを教えてくれる場合を除きます。コメンターが言及したように、これは多くの方法で行うことができます(構造の最初のフィールド、メソッドのパラメーター)。

*最後に、C++ コードを制御できる場合は、データを書き込むバッファの割り当てを行わず、代わりに事前に割り当てられたバッファへのポインタを提供するように変更できる可能性があります。その後、C# コードで必要なサイズに事前に割り当てられたマネージ を C# で作成し、型を使用してそれを固定し、C++ コードへのポインターを提供できます。byte[]GCHandle

于 2012-03-16T06:46:47.457 に答える
9

これを試して:

byte* b = (byte*)intPtr;

安全でないことが必要です(関数シグネチャ、ブロック、またはコンパイラフラグ内/unsafe)。

于 2012-03-16T06:04:28.943 に答える
3

マネージド配列がアンマネージド メモリを占有することはできません。アンマネージド データを一度に 1 チャンクずつコピーして各チャンクを処理するか、データへのアクセスに引き続き Marshal.Copy を使用するインデクサーを取得して提供するUnmanagedArrayクラスを作成することができます。IntPtr

@Vinod が指摘したように、unsafeコードでこれを行うことができます。これにより、C ライクなポインタを使用してメモリに直接アクセスできます。ただし、安全でない .NET メソッドを呼び出す前に、データをマネージド メモリにマーシャリングする必要があるため、独自の C に似たコードにほとんど制限されます。C++ でコードを記述してください。

于 2012-03-16T06:04:10.483 に答える
2

アンマネージ配列を操作するためのソリューションについては、このコード プロジェクトページを確認してください。

于 2012-03-16T06:15:39.860 に答える