How to get IntPtr from byte[] in C#

C#.Net

C# Problem Overview


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

C# Solutions


Solution 1 - C#

Another way,

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

Solution 2 - C#

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.

Solution 3 - C#

Not sure about getting an IntPtr to an array, but you can copy the data for use with unmanaged code by using Mashal.Copy:

IntPtr unmanagedPointer = Marshal.AllocHGlobal(bytes.Length);
Marshal.Copy(bytes, 0, unmanagedPointer, bytes.Length);
// Call unmanaged code
Marshal.FreeHGlobal(unmanagedPointer);

Alternatively you could declare a struct with one property and then use Marshal.PtrToStructure, but that would still require allocating unmanaged memory.

Edit: Also, as Tyalis pointed out, you can also use fixed if unsafe code is an option for you

Solution 4 - C#

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.

Solution 5 - C#

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() :)

Solution 6 - C#

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.

Solution 7 - C#

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.

Attributions

All content for this solution is sourced from the original question on Stackoverflow.

The content on this page is licensed under the Attribution-ShareAlike 4.0 International (CC BY-SA 4.0) license.

Content TypeOriginal AuthorOriginal Content on Stackoverflow
QuestionnetsengView Question on Stackoverflow
Solution 1 - C#user65157View Answer on Stackoverflow
Solution 2 - C#Michaël CarpentierView Answer on Stackoverflow
Solution 3 - C#Richard SzalayView Answer on Stackoverflow
Solution 4 - C#SakthiView Answer on Stackoverflow
Solution 5 - C#dlchambersView Answer on Stackoverflow
Solution 6 - C#David BurgView Answer on Stackoverflow
Solution 7 - C#Alejandro MezcuaView Answer on Stackoverflow