2016-02-24 71 views
1

我在C++中有這樣的結構,我需要轉換爲C#,所以我可以從一個byte []創建這個結構。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異常。

我相信我知道爲什麼,但我不知道如何解決它。 byte[]我有,需要被映射到結構中,並不總是有大小爲548 * 200的Data成員。這個數字是最大的。但似乎我使用的GenericMethod,總是嘗試創建該數據總是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

這當然不行。只需聲明結構*,不包含*數據元素。您可以直接從* 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; 
}; 

和讀取字節數組作爲該數據結構的數據尺寸重新詮釋之後的其餘部分。

你仍然可以使用一系列調用到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

嗯,不是我所期望的,但它做到了訣竅。我希望我能找到一種方法來做到這一點,但仍然在struct中聲明byte []。謝謝。 –