Convert array of structs to IntPtr

前端 未结 4 1063
野性不改
野性不改 2020-12-09 19:53

I am trying to convert an array of the RECT structure (given below) into an IntPtr, so I can send the pointer using PostMessage to another application.

[Stru         


        
相关标签:
4条回答
  • 2020-12-09 20:18

    StructureToPtr expects struct object, and foo is not structure it is array, that is why exception occurs.

    I can suggest you to write structures in cycle (sadly, StructureToPtr does not have overload with Index):

    long LongPtr = ptr.ToInt64(); // Must work both on x86 and x64
    for (int I = 0; I < foo.Length; I++)
    {
        IntPtr RectPtr = new IntPtr(LongPtr);
        Marshal.StructureToPtr(foo[I], RectPtr, false); // You do not need to erase struct in this case
        LongPtr += Marshal.SizeOf(typeof(Rect));
    }
    

    Another option is to write structure as four integers, using Marshal.WriteInt32:

    for (int I = 0; I < foo.Length; I++)
    {
        int Base = I * sizeof(int) * 4;
        Marshal.WriteInt32(ptr, Base + 0, foo[I].Left);
        Marshal.WriteInt32(ptr, Base + sizeof(int), foo[I].Top);
        Marshal.WriteInt32(ptr, Base + sizeof(int) * 2, foo[I].Right);
        Marshal.WriteInt32(ptr, Base + sizeof(int) * 3, foo[I].Bottom);
    }
    

    And the last, you can use unsafe keyword, and work with pointers directly.

    0 讨论(0)
  • 2020-12-09 20:22

    You could try the following:

     RECT[] rects = new RECT[ 4 ];
     IntPtr[] pointers = new IntPtr[4];
     IntPtr result =  Marshal.AllocHGlobal(IntPtr.Size * rects.Length);
     for (int i = 0; i < rects.Length; i++)
     {
         pointers[i] = Marshal.AllocHGlobal (IntPtr.Size);
         Marshal.StructureToPtr(rects[i], pointers[i], true);
         Marshal.WriteIntPtr(result, i * IntPtr.Size, pointers[i]);
     }
     // the array that you need is stored in result
    

    And don't forget to free everything after you are finished.

    0 讨论(0)
  • 2020-12-09 20:23

    Arbiter has given you one good answer for how to marshal arrays of structs. For blittable structs like these I, personally, would use unsafe code rather than manually marshaling each element to unmanaged memory. Something like this:

    RECT[] foo = new RECT[4];
    unsafe
    {
        fixed (RECT* pBuffer = foo)
        {
            //Do work with pointer
        }
    }
    

    or you could pin the array using a GCHandle.

    Unfortunately, you say you need to send this information to another process. If the message you are posting is not one of the ones for which Windows provides automatic marshaling then you have another problem. Since the pointer is relative to the local process it means nothing in the remote process and posting a message with this pointer will cause unexpected behavior, including likely program crash. So what you need to do is write the RECT array to the other process' memory not your own. To do this you need to use OpenProcess to get a handle to the process, VitualAllocEx to allocate the memory in the other process and then WriteProcessMemory to write the array into the other process' virtual memory.

    Unfortunately again, if you are going from a 32bit process to a 32bit process or from a 64bit process to a 64bit process things are quite straightforward but from a 32bit process to a 64bit process things can get a little hairy. VirtualAllocEx and WriteProcessMemory are not really supported from 32 to 64. You may have success by trying to force VirtualAllocEx to allocate its memory in the bottom 4GB of the 64bit memory space so that the resultant pointer is valid for the 32bit process API calls and then write with that pointer. In addition, you may have struct size and packing differences between the two process types. With RECT there is no problem but some other structs with packing or alignment issues might need to be manually written field by field to the 64bit process in order to match the 64bit struct layout.

    0 讨论(0)
  • 2020-12-09 20:40

    I was unable to get this solution to work. So, I did some searching and the solution given here worked for me.

    http://social.msdn.microsoft.com/Forums/en-US/clr/thread/dcfd6310-b03b-4552-b4c7-6c11c115eb45

    0 讨论(0)
提交回复
热议问题