2016-02-24 5 views
1

У меня есть эта структура на C++, которую мне нужно преобразовать в C#, поэтому я могу создать эту структуру из байта [].правильная сортировка структуры C++ в C#

struct TRANS_RECORD_DATA { 
    int size, code; 
    int  ThrowItemCount; 
    int  ItemCount; 
    int  ItemSubStart; 
    int  DataSize; 
    BYTE Data[sizeof(sRECORD_ITEM) * 200]; // sizeof(sRECORD_ITEM) = 548 
}; 

C# версия:

[StructLayout(LayoutKind.Sequential, Pack = 1)] 
struct TRANS_RECORD_DATA { 
    public int size, code; 
     public int ThrowItemCount; 
     public int ItemCount; 
     public int ItemSubStart; 
     public int DataSize; 
     [MarshalAs(UnmanagedType.ByValArray, SizeConst = 548*200)] 
     public byte[] Data; 
    }; 

Я использую эту обобщенную функцию, чтобы дать мне структуру из массива байтов:

T ByteArrayToStructure<T>(byte[] bytes) where T : struct 
{ 
    GCHandle handle = GCHandle.Alloc(bytes, GCHandleType.Pinned); 
    T stuff = (T) Marshal.PtrToStructure(handle.AddrOfPinnedObject(), typeof (T)); 
    handle.Free(); 
    return stuff; 
} 

Но это дает мне:

AccessViolation Exception.

Я верю, что знаю, почему, но я не знаю, как его решить. byte[] У меня есть, который должен быть отображен в структуру, не всегда имеет элемент Data размером 548 * 200. Это число является максимальным. Но кажется, что этот GenericMethod, который я использую, всегда пытаюсь создать структуру с этим Data всегда 548 * 200, а затем он, очевидно, бросит AccessViolation, потому что данные, которые будут отображаться, уже закончены.

Например, этот код:

var bytes = new byte[26]; 
var structure = ByteArrayToStructure<TRANS_RECORD_DATA>(bytes); 

Если вернуть TRANS_RECORD_DATA со всеми теми, ИНТ пользователей с 0 значением, и, наконец, что byte[] Data бы только оставшиеся два байта. (26 - 24 = 2). Но кажется, что он пытается создать полный байт 548 * 200 [] все время, а затем вызывает нарушение доступа.

Есть ли способ решить эту проблему?

+0

Это не может работать, конечно. Просто объявите struct * без * элемента Data. Вы можете получить доступ к данным непосредственно из аргумента * bytes [] *. Он начинается с индекса 24. –

ответ

0

Так как вы объясняете это, независимо от определения C для массива данных длиной 200 * 548 байт, он фактически не полностью выделен или не заполнен внешним неуправляемым кодом, который вы вызываете.

таким образом, ваш единственный способ не определить данные в вашем C# определении структуры:

[StructLayout(LayoutKind.Sequential, Pack = 1)] 
struct TRANS_RECORD_DATA { 
    public int size, code; 
    public int ThrowItemCount; 
    public int ItemCount; 
    public int ItemSubStart; 
    public int DataSize; 
}; 

и после прочтения DataSize повторно интерпретировать оставшуюся часть массива байт в этих структурах данных.

вы все еще можете использовать серию вызовов Marshal.PtrToStructure:

GCHandle handle = GCHandle.Alloc(bytes, GCHandleType.Pinned); 
TRANS_RECORD_DATA stuff = (TRANS_RECORD_DATA) Marshal.PtrToStructure(handle.AddrOfPinnedObject(), typeof (TRANS_RECORD_DATA)); 
var items = new List<sRECORD_ITEM>(stuff.ItemCount); 
for (int i = 0; i < stuff.ItemCount; ++i) 
{ 
    var ptr = handle.AddrOfPinnedObject().Add(i*548) 
    sRECORD_ITEM item = (sRECORD_ITEM)Marshal.PtrToStructure(ptr,typeof(sRECORD_ITEM)); 
} 

Я уверен, что это следует сделать трюк.

+0

Ну, не то, что я ожидал, но он сделал трюк. Я надеялся, что смогу найти способ сделать это, но все же объявить байт [] в структуре. Спасибо. –

Смежные вопросы