Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Marshal.Copy, copying an array of IntPtr into an IntPtr

I can't figure out how does the Copy(IntPtr[], Int32, IntPtr, Int32) method works. I though it could copy the data contained in multiple IntPtrs into a single IntPtr (as MSDN states) but apparently it doesn't work as I expected:

IntPtr[] ptrArray = new IntPtr[]
{
    Marshal.AllocHGlobal(1),
    Marshal.AllocHGlobal(2)
 };

 Marshal.WriteByte(ptrArray[0], 0, 0xC1);

 // Allocate the total size.
 IntPtr ptr = Marshal.AllocHGlobal(3);

 Marshal.Copy(ptrArray, 0, ptr, ptrArray.Length);

 // I expect to read 0xC1 but Value is always random!!
 byte value = Marshal.ReadByte(ptr, 0);

Does someone know if I'm using this method for something that it is not its purpose?

like image 993
mainvoid Avatar asked Nov 27 '14 09:11

mainvoid


People also ask

What is marshal copy in C#?

Copies data from an unmanaged memory pointer to a managed double-precision floating-point number array. public: static void Copy(IntPtr source, cli::array <double> ^ destination, int startIndex, int length); C# Copy.

What is IntPtr C#?

The IntPtr type can be used by languages that support pointers and as a common means of referring to data between languages that do and do not support pointers. IntPtr objects can also be used to hold handles. For example, instances of IntPtr are used extensively in the System. IO.


1 Answers

    static void Main(string[] args)
    {
        IntPtr[] ptrArray = new IntPtr[]
        {
            Marshal.AllocHGlobal(1),
            Marshal.AllocHGlobal(2)
        };

        Marshal.WriteByte(ptrArray[0], 0, 100);

        int size = Marshal.SizeOf(typeof(IntPtr)) * ptrArray.Length;
        IntPtr ptr = Marshal.AllocHGlobal(size);

        Marshal.Copy(ptrArray, 0, ptr, ptrArray.Length);

        // Now we have native pointer ptr, which points to two pointers,
        // each of thme points to its own memory (size 1 and 2).

        // Let's read first IntPtr from ptr:
        IntPtr p = Marshal.ReadIntPtr(ptr);

        // Now let's read byte from p:
        byte b = Marshal.ReadByte(p);

        Console.WriteLine((int)b);    // prints 100

        // To do: release all IntPtr
    }

Read explanations in the comments.

like image 170
Alex F Avatar answered Nov 03 '22 16:11

Alex F