C#嵌套结构封送 - 对象

时间:2017-02-06 22:35:24

标签: c# nested structure marshalling

我有以下嵌套结构。

[StructLayout(LayoutKind.Sequential, Pack = 1)]
struct ERROR_ITEM
{
    byte ErrorID;
};

[StructLayout(LayoutKind.Sequential, Pack = 1)]
struct ERROR_DATA
{
    [MarshalAs(UnmanagedType.ByValArray, ArraySubType = UnmanagedType.Struct, SizeConst = 10)]
    ERROR_ITEM[] ErrorItem;

};

[StructLayout(LayoutKind.Sequential, Pack = 1)]
struct VCP_DATA
{
    [MarshalAs(UnmanagedType.Struct)]
    ERROR_DATA ErrorData;
};

我需要将一个字节数组复制到这个结构中,所以我尝试了以下

vcpBuffer = new VCP_DATA();       
GCHandle handle = GCHandle.Alloc(vcpBuffer, GCHandleType.Pinned);
try
{
    IntPtr pBuffer = handle.AddrOfPinnedObject();
    Marshal.Copy(bytarray, 0, pBuffer, length);
}
finally
{
    if (handle.IsAllocated)
        handle.Free();
}

但是GCHandle.Alloc()返回mscorlib.dll中出现的错误“System.Argument.Execption类型的未处理异常”。 附加信息:对象包含非原始或非blittable数据。

2 个答案:

答案 0 :(得分:1)

vcpBuffer = new VCP_DATA();
GCHandle handle = GCHandle.Alloc(bytearray, GCHandleType.Pinned); 
try 
{ 
    IntPtr pBuffer = handle.AddrOfPinnedObject(); 
    vcpBuffer = (VCP_DATA)Marshal.PtrToStructure(pBuffer, typeof(VCP_DATA)); 
} 
finally 
{ 
    if (handle.IsAllocated) 
        handle.Free(); 
}

答案 1 :(得分:0)

首先,ERROR_ITEM []是一个托管数组,因此它不是一个blittable结构。它只是一个托管参考。引用指向的内存有一个syncblock,方法表指针和位于实际元素前面的长度说明符。

然而,使用'fixed'(https://msdn.microsoft.com/en-us/library/zycewsya.aspxhttps://msdn.microsoft.com/en-us/library/zycewsya.aspx)并没有帮助(但请检查我)。要解决此错误,因为ERROR_ITEM []具有固定长度,只需将数组替换为其中16个ERROR_ITEM字段。您仍然可以对第一个ERROR_ITEMERROR_ITEM*)的地址使用数组语法来访问后续元素。

或者,只计算所有16个元素的大小,但仅包括第一个元素作为字段,然后在Size StructLayout属性上指定ERROR_DATA参数,以便它是足以容纳所有人。

另外,当实际的编译器非常满意时,Resharper有时会抱怨嵌套的东西。但这是因为它是一个阵列。即使是一个固定的不安全的嵌入阵列,C#也认为它在我的经历中是不可思议的。