c# – 非易失性类型的错误
我有这个结构和这个代码:
[StructLayout(LayoutKind.Sequential,Pack = 8)] private class xvid_image_t { [MarshalAs(UnmanagedType.ByValArray,SizeConst = 4)] public int[] stride; // [MarshalAs(UnmanagedType.ByValArray,SizeConst = 4)] // public IntPtr[] plane; } public int decore() { xvid_image_t myStruct = new xvid_image_t(); myStruct.stride = new int[4]; // can be commented out - same result GCHandle.Alloc(myStruct,GCHandleType.Pinned); // ... } 当我尝试运行它,我得到一个ArgumentException说:
阅读this MSDN page后说
我不明白我在做错什么 所以我真正想要的是知道: >为什么? 我正在使用.Net 4.5,但也需要.Net 2.0的解决方案. 解决方法
这是你得到的例外信息.您正在关注消息的“不可消耗”部分,但这不是问题.这是问题的“非原始”部分.数组是非原始数据类型. CLR正试图让你在这里摆脱困境.你可以固定对象,但是你仍然有一个问题,数组不会被固定.当一个对象在需要被固定的字段时并没有被真正固定. 而且,与UnmanagedType.ByValArray有更大的问题,需要进行结构转换.换句话说,您所需的布局与被管理类对象的布局完全不同.只有pinvoke编组可以进行这种转换. 使用fixed关键字,您可以使用固定大小的缓冲区,而不使用pinvoke marshaller来获得所需要的内容.这需要使用不安全的关键字.看起来像这样: [StructLayout(LayoutKind.Sequential)] unsafe private struct xvid_image_t { public fixed int stride[4]; } 请注意,您必须将声明更改为结构类型.它现在是一个值类型,当您将其设置为局部变量时,您不再需要使用GCHandle来锁定该值.确保任何非托管代码通常通过引用获取结构值,不会存储指向结构体的指针.这将会严重恶化,完全不可忽视.不安全的关键字在这里是适当的.如果它存储指针,那么你真的必须使用字节字符串,并使用Marshal.AllocHGlobal()和Marshal.StructureToPtr()来确保指针在非托管代码正在使用时保持有效. (编辑:李大同) 【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容! |