[c#] How to get IntPtr from byte[] in C#

I want to pass a byte[] to a method takes a IntPtr Parameter in C#, is that possible and how?

This question is related to c# .net

The answer is


Another way,

GCHandle pinnedArray = GCHandle.Alloc(byteArray, GCHandleType.Pinned);
IntPtr pointer = pinnedArray.AddrOfPinnedObject();
// Do your stuff...
pinnedArray.Free();

This should work but must be used within an unsafe context:

byte[] buffer = new byte[255];
fixed (byte* p = buffer)
{
    IntPtr ptr = (IntPtr)p;
    // do you stuff here
}

beware, you have to use the pointer in the fixed block! The gc can move the object once you are not anymore in the fixed block.


In some cases you can use an Int32 type (or Int64) in case of the IntPtr. If you can, another useful class is BitConverter. For what you want you could use BitConverter.ToInt32 for example.


Here's a twist on @user65157's answer (+1 for that, BTW):

I created an IDisposable wrapper for the pinned object:

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();
   }
}

then use it like thusly:

using (AutoPinner ap = new AutoPinner(MyManagedObject))
{
   UnmanagedIntPtr = ap;  // Use the operator to retrieve the IntPtr
   //do your stuff
}

I found this to be a nice way of not forgetting to call Free() :)


IntPtr GetIntPtr(Byte[] byteBuf)
{
    IntPtr ptr = Marshal.AllocHGlobal(byteBuf.Length);
    for (int i = 0; i < byteBuf.Length; i++)
    {
       Marshal.WriteByte(ptr, i, byteBuf[i]);
    }
    return ptr;
}

You could use Marshal.UnsafeAddrOfPinnedArrayElement to get a memory pointer to the array (or to a specific element in the array). Keep in mind that the array must be pinned first as per the API documentation:

The array must be pinned using a GCHandle before it is passed to this method. For maximum performance, this method does not validate the array passed to it; this can result in unexpected behavior.


Marshal.Copy works but is rather slow. Faster is to copy the bytes in a for loop. Even faster is to cast the byte array to a ulong array, copy as much ulong as fits in the byte array, then copy the possible remaining 7 bytes (the trail that is not 8 bytes aligned). Fastest is to pin the byte array in a fixed statement as proposed above in Tyalis' answer.