将结构数组转换为IntPtr

Veg*_*sen 11 .net c# marshalling

我试图将RECT结构的数组(下面给出)转换为IntPtr,因此我可以使用PostMessage将指针发送到另一个应用程序.

[StructLayout(LayoutKind.Sequential)]
public struct RECT
{
    public int Left;
    public int Top;
    public int Right;
    public int Bottom;

    // lots of functions snipped here
}

// so we have something to send, in reality I have real data here
// also, the length of the array is not constant
RECT[] foo = new RECT[4]; 
IntPtr ptr = Marshal.AllocHGlobal(Marshal.SizeOf(foo[0]) * 4);
Marshal.StructureToPtr(foo, ptr, true); // -- FAILS
Run Code Online (Sandbox Code Playgroud)

这在最后一行给出了ArgumentException("指定的结构必须是blittable或具有布局信息.").我需要以某种方式使用PostMessage将这个RECT数组转移到另一个应用程序,所以我真的需要一个指向这些数据的指针.

我有什么选择?

更新:这似乎工作:

 IntPtr result = Marshal.AllocHGlobal(Marshal.SizeOf(typeof(Win32.RECT)) * foo.Length);
 IntPtr c = new IntPtr(result.ToInt32());
 for (i = 0; i < foo.Length; i++)
 {
     Marshal.StructureToPtr(foo[i], c, true);
     c = new IntPtr(c.ToInt32() + Marshal.SizeOf(typeof(Win32.RECT)));
 }
Run Code Online (Sandbox Code Playgroud)

再次更新以修复仲裁者评论的内容.

arb*_*ter 13

StructureToPtr需要struct对象,而foo不是结构,而是数组,这就是异常发生的原因.

我建议你在循环中编写结构(遗憾的是,StructureToPtr没有使用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));
}
Run Code Online (Sandbox Code Playgroud)

另一种选择是使用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);
}
Run Code Online (Sandbox Code Playgroud)

最后,您可以使用unsafe关键字,并直接使用指针.