简体   繁体   English

C# 中的编组结构

[英]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";
        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);当我运行此代码时,我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() .您应该将false传递给StructureToPtr()fDeleteOld参数。

By passing true you are asking the marshaller to delete the contents of item .通过传递true您要求编组器删除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.由于您是第一次填写此内容,因此会导致 memory 访问失败,因为 memory 尚未生效。

The documentation states:该文档指出:

StructureToPtr copies the contents of structure to the pre-allocated block of memory that the ptr parameter points to. StructureToPtr 将结构的内容复制到 ptr 参数指向的 memory 的预分配块中。 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 .如果 fDeleteOld 参数为真,则使用嵌入指针上的适当删除方法删除预分配的缓冲区,但缓冲区必须包含有效数据

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));
}

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM