Je veux passer un byte[] à une méthode prend un paramètre IntPtr en c#, est-ce possible et comment.
Réponses
Trop de publicités?Cela devrait fonctionner mais doit être utilisé dans un contexte non sécurisé :
byte[] buffer = new byte[255];
fixed (byte* p = buffer)
{
IntPtr ptr = (IntPtr)p;
// do you stuff here
}
Attention, vous devez utiliser le pointeur dans le bloc fixe ! Le gc peut déplacer l'objet dès que vous n'êtes plus dans le bloc fixe.
Je ne sais pas s'il est possible d'obtenir un IntPtr dans un tableau, mais vous pouvez copier les données pour les utiliser dans un code non géré en utilisant Mashal.Copy :
IntPtr unmanagedPointer = Marshal.AllocHGlobal(bytes.Length);
Marshal.Copy(bytes, 0, unmanagedPointer, bytes.Length);
// Call unmanaged code
Marshal.FreeHGlobal(unmanagedPointer);
Vous pourriez aussi déclarer une structure avec une seule propriété et utiliser Marshal.PtrToStructure, mais cela nécessiterait encore l'allocation de mémoire non gérée.
Editar: De plus, comme Tyalis l'a souligné, vous pouvez également utiliser Correction de si le code non sécurisé est une option pour vous
Voici une variante de la réponse de @user65157 (+1 pour cela, BTW) :
J'ai créé un wrapper IDisposable pour l'objet épinglé :
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();
}
}
puis l'utiliser comme suit :
using (AutoPinner ap = new AutoPinner(MyManagedObject))
{
UnmanagedIntPtr = ap; // Use the operator to retrieve the IntPtr
//do your stuff
}
Je trouve que c'est un bon moyen de ne pas oublier d'appeler Free() :)