Ran*_*agg 12 .net c# struct garbage-collection marshalling
我有这个结构和这段代码:
[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);
// ...
}
Run Code Online (Sandbox Code Playgroud)
当我尝试运行它时,我得到一个ArgumentException说法:
对象包含非原始或非blittable数据
看完这个MSDN页面后说
以下复杂类型也是blittable类型:
blittable类型的一维数组,例如整数数组.但是,包含blittable类型的可变数组的类型本身不是blittable.
仅包含blittable类型的格式化值类型(如果它们被封送为格式化类型,则为类).有关格式化值类型的详细信息,请参阅值类型的默认编组.
我不明白我做错了什么.我不只是想使用Marshal,而是要理解这一点.
所以我真正想知道的是:
我使用的是.Net 4.5,但也需要.Net 2.0的解决方案.
Han*_*ant 14
对象包含非原始或非blittable数据
这是你得到的异常信息.你正专注于信息的"不可眩晕"部分,但这不是问题所在.这是问题的"非原始"部分.数组是非原始数据类型.
CLR正试图让你摆脱困境.您可以固定对象,但是仍然有问题,阵列将不会被固定.当一个对象具有需要固定的字段时,它不会被真正固定.
而且你对UnmanagedType.ByValArray有一个更大的问题,那就是需要进行结构转换.换句话说,您需要的布局与托管类对象的布局完全不同.只有pinvoke marshaller才能进行此转换.
您可以使用fixed关键字通过使用固定大小的缓冲区而不使用pinvoke marshaller来获得您想要的内容.这需要使用unsafe关键字.看起来像这样:
[StructLayout(LayoutKind.Sequential)]
unsafe private struct xvid_image_t {
public fixed int stride[4];
}
Run Code Online (Sandbox Code Playgroud)
请注意,您必须将声明更改为结构类型.它现在是一个值类型,当您将其作为局部变量时,不再需要使用GCHandle来固定该值.确保任何非托管代码通常通过引用获取结构值,不会存储指向结构的指针.这将会严重破坏并完全不可抗拒.在不安全的关键字是合适的位置.如果它确实存储了指针,那么你真的必须对子弹进行字节化并使用Marshal.AllocHGlobal()和Marshal.StructureToPtr()来确保指针在非托管代码使用时保持有效.
| 归档时间: |
|
| 查看次数: |
6511 次 |
| 最近记录: |