C# how to get Byte[] from IntPtr

96,625

Solution 1

Have you looked into Marshal.Copy?

http://msdn.microsoft.com/en-us/library/system.runtime.interopservices.marshal.copy.aspx

Solution 2

If it's a byte[] array:

 byte[] managedArray = new byte[size];
 Marshal.Copy(pnt, managedArray, 0, size);

If it's not byte[], the size parameter in of Marshal.Copy is the number of elements in the array, not the byte size. So, if you had an int[] array rather than a byte[] array, you would have to divide by 4 (bytes per int) to get the correct number of elements to copy, assuming your size parameter passed through the callback refers to the number of bytes.

Solution 3

If you need performance, use it directly:

unsafe { 
    byte *ptr = (byte *)buffer.ToPointer();

    int offset = 0;
    for (int i=0; i<height; i++)
    {
        for (int j=0; j<width; j++)
        {

            float b = (float)ptr[offset+0] / 255.0f;
            float g = (float)ptr[offset+1] / 255.0f;
            float r = (float)ptr[offset+2] / 255.0f;
            float a = (float)ptr[offset+3] / 255.0f;
            offset += 4;

            UnityEngine.Color color = new UnityEngine.Color(r, g, b, a);
            texture.SetPixel(j, height-i, color);
        }
    }
}

Solution 4

According to this Stack Overflow question, you can do the following:

var byteArray = new byte[dataBlockSize];
System.Runtime.InteropServices.Marshal.Copy(payload, byteArray, 0, dataBlockSize);

Solution 5

Span<byte> may be a better solution as it provides most features you need from a byte array. It is faster as you won't need to allocate and copy to a new buffer and safer as you will not have to use directly the pointer.

IntPtr ptr = ... ; 
int ptrLength = ...; 


unsafe
{
    Span<byte> byteArray = new Span<byte>(ptr.ToPointer(), ptrLength);

    for (int i = 0; i < byteArray.Length; i++ )
    {
        // Use it as normalarray array ;
        byteArray[i] = 6;
    }

    // You can always get a byte array . Caution, it allocates a new buffer
    byte[] realByteArray = byteArray.ToArray();
}

It's included in.NET Core 2.1 and a nuget package (System.Memory) for .NET Framework 4.5 + and .NET Core 2.0 +;

Share:
96,625
Gabriel
Author by

Gabriel

C# developer

Updated on July 20, 2022

Comments

  • Gabriel
    Gabriel almost 2 years

    I have a .dll(not my own) that has a delegate. This delegate Callback function is:
    "CallBackFN(ushort opCOde, IntPtr payload, uint size, uint localIP)"

    How can i convert IntPtr to Byte[]? I think that payload is actually Byte[]. If it's not Byte[] and it's something else would i lose some data?

  • Gabriel
    Gabriel over 13 years
    Thanks. I think this is it. If the array is not byte then i will try to change the "size"
  • Bitterblue
    Bitterblue almost 10 years
    +1 for the first half of the answer. Really, the other half doesn't ... I haven't even read it :)
  • Parthi
    Parthi about 6 years
    where we get the dataBlockSize value?
  • Justin Morgan
    Justin Morgan over 5 years
    @Parthi - That depends on what you're doing. The block size is going to be different depending on how much data you're copying.
  • crowder
    crowder over 3 years
    Are you quite sure the ToArray() here does not cause an allocation? In my testing, it seems to.
  • Manuel Amstutz
    Manuel Amstutz almost 3 years
    It is worth mentioning that ToArray causes an allocation and copies the content docs.microsoft.com/en-us/dotnet/api/…