Cómo obtener IntPtr desde byte en C #

Quiero pasar un byte[] a un método toma un parámetro IntPtr en C #, ¿es posible y cómo?

No estoy seguro acerca de cómo obtener un IntPtr en una matriz, pero puede copiar los datos para usar con código no administrado mediante el uso de Mashal.Copia:

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

Alternativamente, podría declarar una estructura con una propiedad y luego usar Marshal.PtrToStructure, pero eso aún requeriría asignar memoria no administrada.

Editar: Además, como señaló Tyalis, también puedes usar un código fijo si no seguro es una opción para ti

De otra manera,

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

Esto debería funcionar, pero debe usarse dentro de un contexto inseguro:

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

¡cuidado, tienes que usar el puntero en el bloque fijo! El gc puede mover el objeto una vez que ya no esté en el bloque fijo.

Puede usar Marshal.UnsafeAddrOfPinnedArrayElement(array, 0) para obtener un puntero de memoria a la matriz.

Aquí hay un giro en la respuesta de @ user65157 (+1 para eso, BTW):

Creé un contenedor IDisposable para el objeto fijado:

 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(); } } 

luego úsalo como así:

 using (AutoPinner ap = new AutoPinner(MyManagedObject)) { UnmanagedIntPtr = ap; // Use the operator to retrieve the IntPtr //do your stuff } 

Encontré que esta es una buena forma de no olvidar llamar Free () 🙂

Marshal.Copy funciona, pero es bastante lento. Más rápido es copiar los bytes en un ciclo for. Incluso más rápido es convertir la matriz de bytes en una matriz ulong, copiar tantos ulong como quepan en la matriz de bytes, luego copiar los 7 bytes restantes (la ruta que no está alineada con 8 bytes). Lo más rápido es fijar la matriz de bytes en una statement fija como se propuso anteriormente en la respuesta de Tyalis.

En algunos casos, puede usar un tipo Int32 (o Int64) en el caso de IntPtr. Si puedes, otra clase útil es BitConverter. Por lo que desea, podría usar BitConverter.ToInt32, por ejemplo.