Vorrei iniziare dicendo che ho cercato e trovato descrizioni dell'uso di fixed {}, Marshal.AllocHGlobal() e GCHandle . Alloc() in tutto questo forum e in molti link sul web. Tuttavia, devo ancora trovare una spiegazione concisa su quando utilizzare la classe Marshal contro la classe GCHandle (con e senza usare fixed {}).Comprensione delle differenze tra l'uso di fixed {}, Marshal.AllocHGlobal() e GCHandle.Alloc()
Sto usando una libreria .NET di terze parti che ha un metodo chiamato Readline() in una classe "Buffer". Il manuale mostra il seguente prototipo di funzione:
bool ReadLine (int x1, int y1, int x2, int y2, System.IntPtr bufData, out int numRead);
con una descrizione di bufData che dice: ... L'area di memoria deve avere un numero di byte maggiore o uguale al tempo della lunghezza della linea il valore restituito dalla proprietà BytesPerPixel.
Ora più avanti nel manuale d'uso che fanno dare un esempio di accesso del buffer (che ho ottimizzato un po 'per il mio esempio specifico):
// 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();
e ho potuto seguire le indicazioni sopra "example" codice con:
// Read one line of buffer data
success = buffer.ReadLine(0, 0, 639, 0, dataLineAddress, out numRead);
// Unpin the array
dataLineHandle.Free()
che potrebbe essere la fine della storia (e devo ancora testare il codice di cui sopra), ma ho finito per googling la classe GCHandle che mi ha spinto verso il basso il percorso di .NET interoperab ility, PInvoke, ecc
Così le mie domande ... 1) Perché non posso usare:
IntPtr dataLineAddress = Marshal.AllocHGlobal(size * 2);
e passare che in ReadLine()?
2) Posso utilizzare il seguente frammento di codice (estratto e ottimizzato dagli esempi sul 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);
}
Mi sarebbe interessato in chiunque può mettere in luce le tecniche di cui sopra e segnalare i miei errori nell'implementazione, nonché sottolineare quando i metodi sopra indicati sono appropriati. Infine, anche se i metodi di cui sopra sono tutti validi, c'è una spinta generale negli ultimi anni verso un approccio o l'altro?
Grazie in anticipo !! Hyped
Sembra un'API orribile. – SLaks