2017-02-06 14 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; 
}; 

мне нужно скопировать массив байтов в этой структуре, поэтому я попытался следующий

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 [] - это управляемый массив, так что это не структура, которая может быть нестабильной. Это просто управляемая ссылка. Память, на которую ссылаются точки, имеет синхроимпульс, указатель таблицы методов и спецификатор длины, расположенный перед фактическими элементами.

Однако использование 'fixed' (https://msdn.microsoft.com/en-us/library/zycewsya.aspxhttps://msdn.microsoft.com/en-us/library/zycewsya.aspx) не поможет (но проверьте меня). Чтобы пройти эту ошибку, поскольку ERROR_ITEM [] имеет фиксированную длину, просто замените массив на 16 из этих полей ERROR_ITEM. Вы можете использовать синтаксис массива по отношению к адресу первого ERROR_ITEM (ERROR_ITEM*) для доступа к последующим элементам.

В качестве альтернативы, просто вычислить размер всех 16 элементов, но включают в себя только первый из них в качестве поля, а затем указать параметр на атрибут StructLayout для ERROR_DATASize так, что он достаточно большой, чтобы держать их всех.

Кроме того, Resharper иногда скулит о вложенных материалах, когда фактический компилятор совершенно доволен им. Но это вызвано тем, что это массив. Даже фиксированный небезопасный массив с массивами заставляет C# думать, что он не может быть использован в моем опыте.

+1

Спасибо за предложения. Я уверен, что они будут работать, но я нашел другой способ сделать то, что мне нужно. vcpBuffer = новый VCP_DATA(); GCHandle handle = GCHandle.Alloc (bytearray, GCHandleType.Pinned); \t try { IntPtr pBuffer = handle.AddrOfPinnedObject(); vcpBuffer = (VCP_DATA) Marshal.PtrToStructure (pBuffer, typeof (VCP_DATA)); } окончательный { если (рукоятка.IsAllocated) ручка.Free(); } – Hassan

+0

@ Hassan - Вы должны сделать ответ и принять его! Это законно сделать это и улучшить сайт. – hoodaticus