Permítanme comenzar diciendo que he buscado y encontrado descripciones del uso de {} fijo, Marshal.AllocHGlobal() y GCHandle .Aloc() a través de este foro y en muchos enlaces en la web. Sin embargo, todavía tengo que encontrar una explicación concisa sobre cuándo usar la clase Marshal frente a la clase GCHandle (con y sin utilizar fixed {}).Comprender la diferencia entre el uso de {} fijo, Marshal.AllocHGlobal() y GCHandle.Alloc()
Estoy usando una biblioteca .NET de terceros que tiene un método llamado Readline() en una clase "Buffer". El manual muestra el siguiente prototipo de función:
bool ReadLine (int x1, int y1, int x2, int y2, System.IntPtr bufData, out int numRead);
con una descripción de bufData que dice: ... El área de memoria debe tener un número de bytes mayores o iguales a la longitud por la línea el valor devuelto por la propiedad BytesPerPixel.
Ahora más adelante en el manual del usuario que hacen dar un ejemplo de acceso a la memoria intermedia (que he retocado un poco para mi ejemplo específico):
// Create an array large enough to hold one line from buffer
int size = 640;
byte[] dataLine = new byte[size * 2]; // 2 bytes per pixel
// Pin the array to avoid Garbage collector moving it
GCHandle dataLineHandle = GCHandle.Alloc(dataLine, GCHandleType.Pinned);
IntPtr dataLineAddress = dataLineHandle.AddrOfPinnedObject();
y pude seguir las indicaciones anteriores "ejemplo" código con:
// Read one line of buffer data
success = buffer.ReadLine(0, 0, 639, 0, dataLineAddress, out numRead);
// Unpin the array
dataLineHandle.Free()
Ese podría ser el final de la historia (y todavía tengo que probar el código anterior), pero terminé googlear la clase GCHandle la que me llevó por el camino de .NET interoperab ility, PInvoke, etc.
Así que mis preguntas ... 1) ¿Por qué no puedo usar:
IntPtr dataLineAddress = Marshal.AllocHGlobal(size * 2);
y pasar eso en ReadLine()?
2) ¿Puedo utilizar el siguiente fragmento de código (extraído y ajustado a partir de ejemplos en la web):
int size = 640;
byte[] dataLine= new byte[size * 2]; // 2 bytes per pixel
// prevent garbage collector from moving buffer around in memory
fixed (byte* fixedDataLine = dataLine)
{
// get IntPtr representing address of first buffer element
IntPtr dataLineAddress= Marshal.UnsafeAddrOfPinnedArrayElement(fixedDataLine , 0);
success = buffer.ReadLine(0, 0, 639, 0, dataLineAddress, out numRead);
}
Estaría interesado en nadie puede arrojar luz sobre las técnicas anteriores y señalar mis errores en la implementación, así como señalar cuándo los métodos anteriores son apropiados. Finalmente, incluso si los métodos anteriores son todos válidos, ¿hay un impulso general en los últimos años hacia un enfoque u otro?
Gracias de antemano! Hyped
Eso suena como una horrible API. – SLaks