2016-02-24 76 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 []。谢谢。 –