2017-02-06 10 views
1

私は以下の入れ子構造を持っています。私はこのような構造にバイト配列をコピーする必要があるので、私は、次のC#ネストされた構造マーシャリング - オブジェクト

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の未処理の例外がエラーを返してみました

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

"mscorlib.dllで発生しました。 追加情報:オブジェクトには、プリミティブでないデータまたはblittable以外のデータが含まれています。

答えて

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構造ではありません。それは単なる管理参照です。参照先のメモリには、実際の要素の前にシンクブロック、メソッドテーブルポインタ、長さ指定子があります。

しかし、「固定」(https://msdn.microsoft.com/en-us/library/zycewsya.aspxhttps://msdn.microsoft.com/en-us/library/zycewsya.aspx)を使用することは助けにはなりません(でもそれについて私をチェックしてください)。このエラーを回避するには、ERROR_ITEM []は固定長であるため、配列をそのフィールドのうちの16個で置き換えてください。最初のERROR_ITEMERROR_ITEM*)のアドレスに対して配列構文を使用して、後続の要素にアクセスすることはできます。

代わりに、ちょうどそれがそれらすべてを保持するのに十分な大きさだようERROR_DATAためStructLayout属性にSizeパラメータを指定し、その後、すべての16個の要素の大きさを計算しますが、フィールドとして最初のものだけが含まれます。

また、実際のコンパイラが完全に満足している場合、Resharperはたぶんネストされたものについて鞭打ちます。しかし、これは配列であるために発生します。固定された安全でないエンベッドされた配列でさえ、C#は自分の経験では不可能だと思います。

+1

ありがとうございます。彼らは働くと確信していますが、私は必要なことをする別の方法を見つけました。 vcpBuffer =新しいVCP_DATA(); GCHandleハンドル= GCHandle.Alloc(bytearray、GCHandleType.Pinned); \t try { IntPtr pBuffer = handle.AddrOfPinnedObject(); vcpBuffer =(VCP_DATA)Marshal.PtrToStructure(pBuffer、typeof(VCP_DATA)); (ハンドル.IsAllocated) handle.Free(); } – Hassan

+0

@ハッサン - あなたはそれを答えて受け入れるべきです!それは正当なものであり、サイトを改善するものです。 – hoodaticus

関連する問題