답변:
배열에 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가 지적했듯이 안전하지 않은 코드가 옵션 인 경우 고정 을 사용할 수도 있습니다
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의 답변을 변형 한 것입니다 (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 () 호출하는 것을 잊지 않는 좋은 방법이라는 것을 알았습니다. :)
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)을 사용할 수 있습니다. 가능하면 또 다른 유용한 클래스는 BitConverter입니다. 예를 들어 BitConverter.ToInt32를 사용할 수 있습니다.
Int32포인터를 정확하고 안전하게 사용할 수있는 유효한 경우는 없습니다 . 이것은 몇 년 전에 행한 나쁜 관행이며 모든 종류의 이식 문제로 이어집니다. 심지어는 Int64이미 증가 128 비트 아키텍처와 포인터의 크기가 있기 때문에 안전하지 않습니다. 포인터는 포인터로만 표시되어야합니다.
int/ 를 사용하는 유일한 시나리오는 사용 long된 언어에 개념이없는 경우입니다 (예 : VB6). C #은 포인터를 지원하며 포인터 를 대신 IntPtr사용할 필요가 전혀 없습니다 int. 답변에 명확한 경고와 잠재적 문제에 대한 설명을 추가하면 내 -1을 제거합니다.