2013-02-18 84 views
1

我希望能夠通過由已知結構組成的TCP/IP接收一些二進制數據。 我不想與C或C++互操作,所以對這種情況有效的解決方案並不能幫助我。 不幸的是,另一方不能改變協議。 當我嘗試讀取給定格式的二進制文件時,也會出現此問題。包含結構數組的Un-/Marshalling嵌套結構

我也檢查了BinaryFormatter和類似的,但他們使用他們自己的格式,這是我不能接受的。

下面是一組結構示例。我希望能夠重建嵌套數組(已知長度)的結構。與當前代碼我得到一個異常:

未能從程序集加載類型「NestedStruct」「...」,因爲它 包含一個對象字段偏移量爲2是不正確地對齊或 通過非重疊對象字段。

我希望能夠發送/接收(或讀取/寫入)struct MainStruct的實例。

[StructLayout(LayoutKind.Explicit, Pack = 1, Size = 244, CharSet = CharSet.Ansi)] 
    public struct NestedStruct 
    { 

     [FieldOffset(0)] 
     public Int16 someInt; 

     [FieldOffset(2), MarshalAs(UnmanagedType.ByValArray, SizeConst = 242)] 
     public Byte[] characterArray; // an array of fixed length 242 

    } 

    [StructLayout(LayoutKind.Explicit)] 
    public struct OtherNestedStruct 
    { 
     [FieldOffset(0)] 
     public Int16 someInt; 
     [FieldOffset(2)] 
     public Int16 someOtherInt; 

    } 


    [StructLayout(LayoutKind.Explicit)] 
    public struct MainStruct 
    { 
     [FieldOffset(0)] 
     public double someDouble; 
     [FieldOffset(8)] 
     public NestedStruct nestedContent; 
     [FieldOffset(8 + 244)] 
     [MarshalAs(UnmanagedType.ByValArray, SizeConst = 13 * 4)] 
     public OtherNestedStruct[] arrayOfStruct; // fixed array length 13 

    } 

UPDATE:

這裏是我的最新版本:

[StructLayout(LayoutKind.Sequential, Pack = 1)] 
    public struct NestedStruct 
    { 

     public Int16 someInt; 

     [MarshalAs(UnmanagedType.ByValArray, ArraySubType = UnmanagedType.U1, SizeConst = 242)] 
     public Byte[] characterArray; // an array of fixed length 242 

    } 

    [StructLayout(LayoutKind.Sequential , Pack=1)] 
    public struct OtherNestedStruct 
    { 
     public Int16 someInt; 
     public Int16 someOtherInt; 

    } 


    [StructLayout(LayoutKind.Sequential, Pack=1)] 
    public struct MainStruct 
    { 

     public double someDouble; 

     public NestedStruct nestedContent; 

     [MarshalAs(UnmanagedType.ByValArray, ArraySubType = UnmanagedType.Struct, SizeConst = 13)] 
     public OtherNestedStruct[] arrayOfStruct; // fixed array length 13 

    } 
+0

您是否嘗試過在characterArray去除[FieldOffset]? – Hylaean 2013-02-18 10:51:17

+0

@Hylaean:是的。甚至不編譯「標記有StrcutLayout(LayoutKind.Explicit)的實例字段類型必須具有FieldOffset屬性」。 – Onur 2013-02-18 10:54:04

+0

並切換到LayoutKind.Sequential :) – Hylaean 2013-02-18 11:08:07

回答

1

必須指定ArraySubType

[StructLayout(LayoutKind.Sequential, Pack = 1)] 
    public struct NestedStruct 
    { 
     public Int16 someInt; 
     [MarshalAs(UnmanagedType.ByValArray, ArraySubType = UnmanagedType.U1, SizeConst = 242)] 
     public Byte[] characterArray; // an array of fixed length 242 
    } 

    [StructLayout(LayoutKind.Sequential, Pack = 1)] 
    public struct OtherNestedStruct 
    { 
     public Int16 someInt; 
     public Int16 someOtherInt; 

    } 


    [StructLayout(LayoutKind.Sequential, Pack = 1)] 
    public struct MainStruct 
    { 
     public double someDouble; 
     public NestedStruct nestedContent; 
     [MarshalAs(UnmanagedType.ByValArray, SizeConst = 13 * 4)] 
     public OtherNestedStruct[] arrayOfStruct; // fixed array length 13 

    } 

    static void Main(string[] args) 
    { 
     var x = Marshal.SizeOf(typeof(MainStruct)); 
     //x == 460 
    } 
+0

'NestedStruct'現在按預期工作(至少轉換爲字節)。我現在試試其餘的...... – Onur 2013-02-18 12:01:36

+0

我不得不調整一些'bool'成員,但它現在可以工作! – Onur 2013-02-18 13:50:41