Per questo è anche possibile utilizzare un array di byte.
A tale scopo, impiegando la procedura non sicura e la dichiarazione fissa:
static unsafe void PerformOperation()
{
byte[] buf = new byte[1024];
fixed (void* ptr = &buf[0])
{
SomeUnmanagedFunction(new IntPtr(ptr));
}
}
Il problema - e questo è molto importante - è che SomeUnmanagedFunction non è permesso di toccare quel puntatore dopo che è tornato e il codice è uscito dal blocco fisso. Quindi, se fai qualcosa di simile:
static void PerformFabulousTrick()
{
byte[] buf = new byte[1024];
fixed (void *ptr = &buf[0])
{
SetBuffer(ptr, buf.Length);
}
FillBuffer(); // puts data in buf - NOT - may crash hard
}
non stai chiedendo altro che guai. In questo caso, probabilmente si desidera utilizzare uno GCHandle, che può bloccare un oggetto gestito nell'heap. Questo può anche essere fastidioso nel fatto che è necessario sbloccarlo tempestivamente o rischiare di frammentare il tuo heap.
In generale, ti consiglio di assicurarti di inserire P/Invocare correttamente la funzione in modo che il marshaller possa farlo per te. Mi piace riparato meglio di GlobalAlloc poiché il suo scopo è chiaro. Non riesco a decidere quale mi piace meno di GlobalAlloc e GCHandle. Entrambi richiedono di fare più lavoro poiché il GC o la lingua non lo faranno per te.
E il 'nuovo byte [1024]'? –
@John Saunders: Non so se sarebbe affidabile dato che la memoria gestita non è garantita come contigua. Probabilmente vorrai appenderlo anche per evitare che il GC lo sposti mentre era in uso. – Joshua
@Joshua Huh? La memoria gestita è garantita per essere contigua. Non è garantito rimanere nello stesso posto, ma quando lo fa, è contiguo, e c'è "riparato" per mantenerlo stabile. –