Как получить IntPtr из байта [] в С#

Я хочу передать byte[] методу, который принимает параметр IntPtr в С#, это возможно и как?

Ответ 1

Не уверен в получении IntPtr для массива, но вы можете скопировать данные для использования с неуправляемым кодом с помощью Mashal.Copy:

IntPtr unmanagedPointer = Marshal.AllocHGlobal(bytes.Length);
Marshal.Copy(bytes, 0, unmanagedPointer, bytes.Length);
// Call unmanaged code
Marshal.FreeHGlobal(unmanagedPointer);

В качестве альтернативы вы можете объявить структуру с одним свойством, а затем использовать Marshal.PtrToStructure, но это все равно потребует выделения неуправляемой памяти.

Изменить: Кроме того, как указал Тайлис, вы также можете использовать исправление, если для вас есть опция

Ответ 2

Другой способ,

GCHandle pinnedArray = GCHandle.Alloc(byteArray, GCHandleType.Pinned);
IntPtr pointer = pinnedArray.AddrOfPinnedObject();
// Do your stuff...
pinnedArray.Free();

Ответ 3

Это должно работать, но должно использоваться в небезопасном контексте:

byte[] buffer = new byte[255];
fixed (byte* p = buffer)
{
    IntPtr ptr = (IntPtr)p;
    // do you stuff here
}

Остерегайтесь, вы должны использовать указатель в фиксированном блоке! Gc может перемещать объект, как только вы больше не находитесь в фиксированном блоке.

Ответ 4

Вы можете использовать Marshal.UnsafeAddrOfPinnedArrayElement(array, 0), чтобы получить указатель на память массива.

Ответ 5

Здесь твист на @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():)

Ответ 6

Маршал. Копи работает, но довольно медленный. Более быстрая копия байтов в цикле for. Еще быстрее сделать массив байтов массивом ulong, скопировать столько же, сколько подходит в массив байтов, а затем скопировать оставшиеся 7 байтов (след, который не соответствует 8 байтам). Самый быстрый - связать массив байтов в фиксированном утверждении, как было предложено выше в ответе Tyalis.

Ответ 7

В некоторых случаях вы можете использовать Int32-тип (или Int64) в случае IntPtr. Если вы можете, другим полезным классом является BitConverter. Для чего вы хотите использовать BitConverter.ToInt32, например.