我有这样的结构与此代码:
[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
话说:
对象包含非原始或非blittable数据
看完这个MSDN网页说法
下面复杂的类型也Blittable型:
我不明白我在做什么错。 我不只是想用Marshal
,但要明白这一点。
那么,其实我是想的是要知道:
- 为什么?
- 我怎样才能解决这个问题?
- 你会还提供了解决方案,在该结构中的注释行工作?
我使用.NET 4.5,但还需要对.NET 2.0的解决方案。
对象包含非原始或非blittable数据
这就是你得到的异常信息。 你正专注于该消息的“非blittable”的一部分,但是这不是问题。 这是“非基本”部分这是个问题。 阵列是一个非原始数据类型。
CLR是试图让你摆脱困境这里。 你可以钉住对象,但那么你仍然有问题,阵列将无法固定。 一个对象是不是真正的寄托,当它具有需要被固定为井场。
而你与UnmanagedType.ByValArray,需要一个结构转换一个更大的问题。 换句话说,你需要的布局是从托管类对象的布局完全不同。 只有PInvoke的编组可以进行这种转换。
你可以得到你想要的东西,而不使用固定大小的缓冲区,使用固定的关键字使用的PInvoke编组。 这需要使用不安全的关键字。 使它看起来像这样:
[StructLayout(LayoutKind.Sequential)]
unsafe private struct xvid_image_t {
public fixed int stride[4];
}
请注意,您必须声明更改为结构类型。 现在它是值类型,您不再需要使用的GCHandle管脚值时,你把它的局部变量。 请务必注意什么非托管代码采用结构值,通常由参考, 不存储的指针结构。 那将糟糕,完全undiagnosably炸毁。 不安全的关键字是合适的位置。 如果它存储指针,那么你真的要字节子弹和使用Marshal.AllocHGlobal()和Marshal.StructureToPtr(),以确保当非托管代码在使用它的指针保持有效。
.NET的一个恼人的限制是,它识别该唯一阵列肥胖型东西都是一个独立System.Array
对象和System.String
,这两者都是引用类型。 有可能为C#编写的代码来使用一个fixed
阵列(如由Hans帕桑特说明),但是这样的类型不受.NET本身的认可,并且其使用固定阵列代码不核查。 此外,固定的阵列限定为保持原语,并且不能被其他语言如vb.net进行访问。
两种替代方案使用固定阵列是
与它们一起共适当大小字段的一些组合取代定阵列(使用N个变量在大多数情况下,但或许替换例如char[4]
与UInt32
,或char[8]
用UInt64
)。 如果数组不太大,人们可以限定(通过剪切/粘贴或反射)的一组,其通过参考文献采取一个结构和读/写正确的元件,然后创建代表的阵列,以调用这样的方法静态方法。
以与阵列更换整个结构,然后传递阵列作为第一元件ref
参数。 这可能甚至超过使用“危险”的fixed
结构内的数组,但我知道在vb.net只有这样,才能得到“传址裁判”的语义与包含的东西,真正需要的结构作为阵列访问。
虽然我可以理解,价值型数组也可能被认为是“混乱”(特别是如果他们是自动盒装)有在那里他们将一直为阵列存储语义正确的做法的地方,无论是从允许的角度来看pass-通过-REF为COM互操作,并且还从将要用于返回一个小数量的值的方法的观点考虑语义。 例如,在System.Drawing2d
,存在返回当前图形变换为一个方法float[6]
; 不是通过实验等,就知道修改该数组则返回后会影响,是否会影响到没有明确的方式,或保证不会影响任何东西。 如果该方法返回一个值类型的数组,这将是清楚的是改变返回数组可以在不影响任何东西。 尽管如此,价值型阵列是否会一直框架的有用的部分,但事实上,无论是好还是坏的原因,没有这样的事情存在。
我把下面的答案从这个链接( 点击这里 )
SItuLongEmailMsg msg = newSItuLongEmailMsg();
// set members
msg.text = new byte[2048];
// assign to msg.text
int msgSize = Marshal.SizeOf(msg);
IntPtr ptr = Marshal.AllocHGlobal(msgSize);
Marshal.StructureToPtr(msg, ptr, true);
byte[] dataOut = new byte[msgSize];
Marshal.Copy(ptr, dataOut, 0, msgSize);