marshaling structure in C#
I have this piece of code and it generates an error:
[StructLayout(LayoutKind.Sequential, Pack = 1)]
public struct MyItem
{
[MarshalAs(UnmanagedType.LPWStr)]
public string Name;
public int ID;
public double ID1;
}
private void button1_Click(object sender, RoutedEventArgs e)
{
MyItem[] items = new MyItem[6];
items[0].Name = "JFK";
items[0].ID = 35;
items[1].Name = "LBJ";
items[1].ID = 36;
items[2].Name = "Tricky Dicky";
开发者_如何学Go items[2].ID = 37;
items[3].Name = "Gerald Ford";
items[3].ID = 38;
items[4].Name = "Jimmy Carter";
items[4].ID = 39;
items[5].Name = "Ronald Reagan";
items[5].ID = 40;
IntPtr itemsPtr = Marshal.AllocHGlobal(Marshal.SizeOf(typeof(MyItem)) *
items.Length);
try
{
IntPtr item = new IntPtr(itemsPtr.ToInt32());
for (int i = 0; i < items.Length; i++)
{
Marshal.StructureToPtr(items[i], item, true);
item = new IntPtr(item.ToInt32() + Marshal.SizeOf(typeof(MyItem)));
}
}
finally
{
Marshal.FreeHGlobal(itemsPtr);
}
When I run this code, I am getting write protection error in
Marshal.StructureToPtr(items[i], item, true);
What is the problem and how do I solve it?
You should be passing false
to the fDeleteOld
parameter of StructureToPtr()
.
By passing true
you are asking the marshaller to delete the contents of item
. Since you are filling this out for the first time, this results in a memory access failure because the memory is not yet valid.
The documentation states:
StructureToPtr copies the contents of structure to the pre-allocated block of memory that the ptr parameter points to. If the fDeleteOld parameter is true, the pre-allocated buffer is deleted with the appropriate deletion method on the embedded pointer, but the buffer must contain valid data.
The emphasis is mine.
Incidentally I think the loop code looks neater like this:
Int32 addr = itemsPtr.ToInt32();
for (int i = 0; i < items.Length; i++)
{
Marshal.StructureToPtr(items[i], new IntPtr(addr), false);
addr += Marshal.SizeOf(typeof(MyItem));
}
精彩评论