2017-02-06 4 views
1

다음 중첩 구조가 있습니다.C# 중첩 구조체 마샬링 - 개체

[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; 
}; 

I이 구조 바이트 배열 복사해야하므로 I는 다음

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()가 오류 "형 System.Argument.Execption 처리되지 않은 예외 리턴 시도 "mscorlib.dll에서 발생했습니다. 추가 정보 : 개체에 비 프리미티브 또는 비 블릿 데이터가 포함되어 있습니다.

답변

0
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(); 
} 
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 []이 고정 길이이므로 배열을 그 중 ERROR_ITEM 개 필드 중 16 개로 바꾸십시오. 첫 번째 ERROR_ITEM (ERROR_ITEM*)의 주소에 대해 배열 구문을 사용하여 후속 요소에 액세스 할 수 있습니다.

다른 방법은, 그냥 그들 모두를 저장하기에 충분히 크다 있도록 다음 ERROR_DATA에 대한 StructLayout 속성에 Size 매개 변수를 지정, 16 개 요소의 크기를 계산하지만, 필드로 첫 번째 하나를 포함한다.

또한 Resharper는 실제 컴파일러가 완전히 만족 스러울 때 중첩 된 항목에 대해 때로는 말을합니다. 그러나 이것은 배열로 인해 발생합니다. 고정 된 안전하지 않은 임베드 된 배열조차도 C#이 내 경험 에선 방해 할 수 없다고 생각합니다.

+1

제안 해 주셔서 감사합니다. 나는 그들이 일할 것이라고 확신하지만, 내가 필요한 것을하는 다른 방법을 발견했다. vcpBuffer = 새 VCP_DATA(); GCHandle handle = GCHandle.Alloc (bytearray, GCHandleType.Pinned); \t 시도 { IntPtr pBuffer = handle.AddrOfPinnedObject(); vcpBuffer = (VCP_DATA) Marshal.PtrToStructure (pBuffer, typeof (VCP_DATA)); } 마침내 { if (handle.IsAllocated) handle.Free(); } – Hassan

+0

@ 하산 - 해답을 만들어 받아 들여야합니다! 그렇게하는 것이 합법적이며 사이트를 향상시킵니다. – hoodaticus

관련 문제