L'approccio migliore sarebbe quello di fare una classe di estensione che ha fatto questo per voi, per ogni tipo. Non è possibile renderlo generico poiché Marshal.Copy()
non supporta un tipo generico. Quindi si dovrà duplicare il vostro metodo per ogni tipo byte
, char
, int
, long
, float
, double
, ecc, tuttavia, è possibile effettuare un metodo di supporto generico per determinare la dimensione di Marshsal
.
Qualcosa come di seguito potrebbe essere utile a voi:
public static class MarshalExtender
{
public static IntPtr CopyToCoTaskMem(this byte[] array)
{
var ptr = AllocArrayCoTaskMem(array);
Marshal.Copy(array, 0, ptr, array.Length);
return ptr;
}
// Copy the above method and replace types as needed (int, double, etc).
// Helper method for allocating bytes with generic arrays.
static IntPtr AllocArrayCoTaskMem<T>(T[] array)
{
var type = typeof(T);
var size = Marshal.SizeOf(type) * array.Length;
return Marshal.AllocCoTaskMem(size);
}
}
Il vantaggio principale è nel codice si potrebbe facilmente fare qualcosa di simile:
var myArray = { 0, 1, 2, 3, 4, 5, ... }
var ptr = myArray.CopyToCoTaskMem();
NOTA: Basta essere sicuri di chiamare Marshal.FreeCoTaskMem()
quando hai finito! Raccomanderei il metodo di estensione che restituisce un oggetto IDisposable
in modo da poterlo racchiudere in un blocco using
.
Ad esempio:
public sealed class CoTaskMemoryHandle : IDisposable
{
bool isDisposed;
readonly IntPtr handle;
public IntPtr Handle { get { return handle; } }
public CoTaskMemoryHandle(IntPtr handle)
{
this.handle = handle;
}
public void Dispose()
{
OnDispose(true);
GC.SuppressFinalize(this);
}
void OnDispose(bool isDisposing)
{
if (isDisposed) return;
if (isDisposing)
{
if (handle != IntPtr.Zero)
Marshal.FreeCoTaskMem(handle);
}
isDisposed = true;
}
}
Allora il tuo metodo di una classe di estensione modificata:
public static CoTaskMemoryHandle CopyToCoTaskMem(this byte[] array)
{
var ptr = AllocArrayCoTaskMem(array);
Marshal.Copy(array, 0, ptr, array.Length);
return new CoTaskMemoryHandle(ptr);
}
questo modo si può incapsulare in modo sicuro il bilanciamento Alloc
/Free
:
using(myArray.CopyToCoTaskMem())
{
// Do something here..
}
che cosa hai bisogno l'intptr per - che determina come verrebbe eseguito il marshalling. –
Vuoi effettivamente una copia, o solo un [puntatore a un array bloccato] (http://stackoverflow.com/a/4097057/11683)? – GSerg
Toolkit Modelli di trasformazione del testo. T4 in breve. – Theraot