Как получить IntPtr из byte[] в C#
Я хочу передать a byte[]
к методу принимает в C# это возможно и как?
7 ответов:
Не уверен в получении IntPtr в массив, но вы можете скопировать данные для использования с неуправляемым кодом с помощью Mashal.Копия:
IntPtr unmanagedPointer = Marshal.AllocHGlobal(bytes.Length); Marshal.Copy(bytes, 0, unmanagedPointer, bytes.Length); // Call unmanaged code Marshal.FreeHGlobal(unmanagedPointer);
в качестве альтернативы вы можете объявить структуру с одним свойством, а затем использовать Маршал.PtrToStructure, но это все равно потребует выделения неуправляемой памяти.
Edit: кроме того, как отметил Тялис, вы также можете использовать основные если небезопасный код является опцией для вас
другой путь,
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 для этого, кстати):
Я создал 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.