C #에서 매개 변수 byte[]
를 사용하는 메서드에 a 를 전달하고 싶습니다. IntPtr
가능합니까?
답변
배열에 IntPtr을 가져 오는 것에 대해 확실하지 않지만 Mashal.Copy를 사용하여 관리되지 않는 코드와 함께 사용할 데이터를 복사 할 수 있습니다.
IntPtr unmanagedPointer = Marshal.AllocHGlobal(bytes.Length);
Marshal.Copy(bytes, 0, unmanagedPointer, bytes.Length);
// Call unmanaged code
Marshal.FreeHGlobal(unmanagedPointer);
또는 하나의 속성으로 구조체를 선언 한 다음 Marshal.PtrToStructure를 사용할 수 있지만 여전히 관리되지 않는 메모리를 할당해야합니다.
편집 : 또한 Tyalis가 지적했듯이 안전하지 않은 코드가 옵션 인 경우 고정 을 사용할 수도 있습니다
답변
또 다른 방법,
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의 답변을 변형 한 것입니다 (BTW의 경우 +1).
고정 된 개체에 대한 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 () 호출하는 것을 잊지 않는 좋은 방법이라는 것을 알았습니다. 🙂
답변
원수. 복사는 작동하지만 속도가 느립니다. for 루프에서 바이트를 복사하는 것이 더 빠릅니다. 더 빠른 방법은 바이트 배열을 ulong 배열로 캐스트하고 바이트 배열에 맞는만큼 ulong을 복사 한 다음 남은 7 바이트 (8 바이트가 정렬되지 않은 트레일)를 복사하는 것입니다. Tyalis의 답변에서 위에서 제안한 것처럼 고정 배열로 바이트 배열을 고정하는 것이 가장 빠릅니다.
답변
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;
}