blittable 类型上的非 blittable 错误 [英] Non-blittable error on a blittable type

查看:15
本文介绍了blittable 类型上的非 blittable 错误的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我有这个结构和这个代码:

I have this struct and this code:

[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 说:

When I try to run it I get an ArgumentException saying:

对象包含非原始或非 blittable 数据

Object contains non-primitive or non-blittable data

阅读这个MSDN页面后说

以下复杂类型也是 blittable 类型:

The following complex types are also blittable types:

  • blittable 类型的一维数组,例如整数数组.但是,包含 blittable 类型的可变数组的类型本身并不是 blittable.

  • One-dimensional arrays of blittable types, such as an array of integers. However, a type that contains a variable array of blittable types is not itself blittable.

仅包含 blittable 类型的格式化值类型(如果它们被封送为格式化类型,则还包含类).有关格式化值类型的详细信息,请参阅值类型的默认封送处理.

Formatted value types that contain only blittable types (and classes if they are marshaled as formatted types). For more information about formatted value types, see Default Marshaling for Value Types.

我不明白我做错了什么.我不只是想使用 Marshal,还要理解这一点.

I don't understand what I am doing wrong. I don't just want to use Marshal, but to understand this too.

所以我真正想知道的是:

So what I actually want is to know:

  1. 为什么?
  2. 我该如何解决这个问题?
  3. 您提供的解决方案是否也适用于结构中的注释行?

我使用的是 .Net 4.5,但还需要一个适用于 .Net 2.0 的解决方案.

I am using .Net 4.5 but a solution for .Net 2.0 is also needed.

推荐答案

对象包含非原始或非 blittable 数据

Object contains non-primitive or non-blittable data

这就是你得到的异常信息.您正在关注消息的非 blittable"部分,但这不是问题.问题在于非原始"部分.数组是一种非原始数据类型.

That's the exception message you get. You are focusing on the "non-blittable" part of the message, but that's not the problem. It is the "non-primitive" part that's the issue. An array is a non-primitive data type.

CLR 正试图让您远离这里的麻烦.您可以固定该对象,但随后您仍然 遇到问题,该数组将不会被固定.当一个对象也有需要固定的字段时,它并没有真正固定.

The CLR is trying to keep you out of trouble here. You could pin the object but then you still have a problem, the array won't be pinned. An object isn't truly pinned when it has fields that need to be pinned as well.

您在 UnmanagedType.ByValArray 上有一个更大的问题,需要进行结构转换.换句话说,您需要的布局与托管类对象的布局完全不同.只有 pinvoke 编组器可以进行此转换.

And you have a bigger problem with the UnmanagedType.ByValArray, that requires a structural conversion. In other words, the layout that you need is completely different from the layout of the managed class object. Only the pinvoke marshaller can make this conversion.

通过使用固定大小的缓冲区,使用 fixed 关键字,您可以在不使用 pinvoke 编组器的情况下获得所需的内容.这需要使用 unsafe 关键字.让它看起来像这样:

You can get what you want without using the pinvoke marshaller by using fixed size buffers, using the fixed keyword. This requires using the unsafe keyword. Make it look like this:

    [StructLayout(LayoutKind.Sequential)]
    unsafe private struct xvid_image_t {
        public fixed int stride[4];
    }

请注意,您必须将声明更改为 struct 类型.它现在是一种值类型,当您将其设为局部变量时,您不再需要使用 GCHandle 来固定该值.请确保任何非托管代码通常通过引用获取结构值,存储指向该结构的指针.那将爆炸严重且完全无法诊断.unsafe 关键字在这里很合适.如果它确实存储了指针,那么您确实必须对项目符号进行字节处理并使用 Marshal.AllocHGlobal() 和 Marshal.StructureToPtr() 来确保指针在非托管代码使用时保持有效.

Note that you have to change the declaration to a struct type. It is now a value type, you no longer need to use GCHandle to pin the value when you make it a local variable. Do make sure that whatever unmanaged code takes the structure value, usually by reference, does not store a pointer to the struct. That's going to blow up badly and utterly undiagnosably. The unsafe keyword is appropriate here. If it does store the pointer then you really do have to byte the bullet and use Marshal.AllocHGlobal() and Marshal.StructureToPtr() to ensure the pointer stays valid while the unmanaged code is using it.

这篇关于blittable 类型上的非 blittable 错误的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆