C#でパラメーターをbyte[]取るメソッドにa を渡したいのですIntPtrが、それは可能ですか?
GCHandleメソッドはチャームのように機能します... fixedメソッドでもあります。:P :))
C#でパラメーターをbyte[]取るメソッドにa を渡したいのですIntPtrが、それは可能ですか?
GCHandleメソッドはチャームのように機能します... fixedメソッドでもあります。:P :))
回答:
IntPtrを配列に取得するかどうかはわかりませんが、Mashal.Copyを使用して、アンマネージコードで使用するためにデータをコピーできます。
IntPtr unmanagedPointer = Marshal.AllocHGlobal(bytes.Length);
Marshal.Copy(bytes, 0, unmanagedPointer, bytes.Length);
// Call unmanaged code
Marshal.FreeHGlobal(unmanagedPointer);
または、1つのプロパティで構造体を宣言してから、Marshal.PtrToStructureを使用することもできますが、その場合でも、アンマネージメモリを割り当てる必要があります。
編集:また、Tyalisが指摘したように、安全でないコードがオプションである場合は、fixedを使用することもできます
Marshal.Copy、そのオーバーロードには開始インデックスが必要です。コールはする必要がありますMarshal.Copy(bytes, 0, unmanagedPointer, bytes.Length);
別の方法、
GCHandle pinnedArray = GCHandle.Alloc(byteArray, GCHandleType.Pinned);
IntPtr pointer = pinnedArray.AddrOfPinnedObject();
// Do your stuff...
pinnedArray.Free();
これは機能するはずですが、安全でないコンテキスト内で使用する必要があります。
byte[] buffer = new byte[255];
fixed (byte* p = buffer)
{
IntPtr ptr = (IntPtr)p;
// do you stuff here
}
注意してください、あなたは固定ブロックでポインタを使わなければなりません!固定ブロックから離れると、GCはオブジェクトを移動できます。
Marshal.UnsafeAddrOfPinnedArrayElement(array, 0)配列へのメモリポインタを取得するために使用できます。
@ user65157の答えにひねりを加えました(そのための+ 1、BTW)。
固定されたオブジェクトのIDisposableラッパーを作成しました。
class AutoPinner : IDisposable
{
GCHandle _pinnedArray;
public AutoPinner(Object obj)
{
_pinnedArray = GCHandle.Alloc(obj, GCHandleType.Pinned);
}
public static implicit operator IntPtr(AutoPinner ap)
{
return ap._pinnedArray.AddrOfPinnedObject();
}
public void Dispose()
{
_pinnedArray.Free();
}
}
次に、このように使用します:
using (AutoPinner ap = new AutoPinner(MyManagedObject))
{
UnmanagedIntPtr = ap; // Use the operator to retrieve the IntPtr
//do your stuff
}
これは、Free()を呼び出すのを忘れないための良い方法であることがわかりました:)
IntPtr GetIntPtr(Byte[] byteBuf)
{
IntPtr ptr = Marshal.AllocHGlobal(byteBuf.Length);
for (int i = 0; i < byteBuf.Length; i++)
{
Marshal.WriteByte(ptr, i, byteBuf[i]);
}
return ptr;
}
IntPtrの場合は、Int32型(またはInt64)を使用できる場合があります。可能であれば、もう1つの便利なクラスはBitConverterです。たとえば、BitConverter.ToInt32を使用できます。
Int32ポインタとして正しく安全に使用できる有効なケースはありません。これは何年も前に行われた悪い習慣であり、あらゆる種類の移植の問題につながりました。Int64128ビットアーキテクチャが既に存在し、ポインタサイズが大きくなるため、安全ではありません。ポインターは、ポインターとしてのみ表現する必要があります。
int/ を使用するための唯一の有効なシナリオlongは、使用される言語にそれらの概念がない場合です(たとえば、VB6)。C#はポインターをサポートしており、ポインターの代わりにIntPtrを使用する必要はまったくありませんint。明確な警告と潜在的な問題の説明を回答に追加した場合、私は-1を削除します。