我正在尝试将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
这将在最后一行给出一个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))); }
解决方法
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)); }
另一种选择是使用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); }
最后,您可以使用不安全的关键字,并直接使用指针.