Я хочу передать byte[]
методу, который принимает параметр IntPtr
в С#, это возможно и как?
Как получить 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, например.