6

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?

2
  • IntPtr ptr = Marshal.AllocHGlobal(3 * sizeof(IntPtr)); Commented Nov 27, 2014 at 9:52
  • Do keep in mind what you are copying. You are only copying the pointer values, not the values that the pointers are pointing to. Arbitrarily, Marshal.ReadByte(Marshal.ReadIntPtr(ptr), 0) gives you that byte back. But surely isn't what you had in mind. Commented Nov 27, 2014 at 10:26

1 Answer 1

2
    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.

Sign up to request clarification or add additional context in comments.

3 Comments

If that is right then I find the comment on Marshal.Copy Method (IntPtrArray, Int32, IntPtr, Int32) : Copies data from a one-dimensional, managed IntPtr array to an unmanaged memory pointer rather misleading as not the data but the pointers are copied..!? - Also: This does not create a contiguous memory area, so to access a random byte will be a hassle, right, or there some magic at work?
This means, that this method copies pointers to unmanaged memory area. Each pointer may point to some other memory. If you want to have an array which contains two other unmanaged arrays, allocate 3 bytes (in your case) and apply Marshal.Copy Method (IntPtr,Byte[], Int32, Int32) twice.
Correction: you need to read every IntPtr to 2 managed byte arrays first: Marshal.Copy Method (IntPtr,Byte[], Int32, Int32), then copy from them to 3-byte unmanaged block, applying twice Marshal.Copy Method (Byte[], Int32, IntPtr, Int32). Or use CopyMemory API (direct copy between two unmanaged memory blocks).

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.