c# Marshal 將字節數組轉為結構 封裝協議


解析網絡協議如果使用依次讀取字節的方式效率太低,可以直接通過結構體映射的方式來轉換數據,如下

  1. 定義需要轉換的結構體
    需要讓結構體數據順序排列並對齊
    依次定義每一個屬性的長度即可,需要注意定義的數據類型的大小要與UnmanagedType類型定義的大小一直
    否則會報 “不能作為非托管結構進行封送處理;無法計算有意義的大小或偏移量”
 // [StructLayout(LayoutKind.Sequential, Pack = 1)] //順序排列,並按1字節對齊 
    [StructLayoutAttribute(LayoutKind.Sequential, CharSet = CharSet.Ansi, Pack = 1)]
    public struct SEG2
    {
        /// <summary>
        /// 文件描述符  0-1
        /// 若不是3A55H/553AH則 不是SEG2文件
        /// </summary>
        [MarshalAs(UnmanagedType.U1)]
        public byte Descriptor0;

        [MarshalAs(UnmanagedType.U1)]
        public byte Descriptor1;
}
  1. 將字節數組轉為對象
var fileByte = File.ReadAllBytes(testFile);
//創建指定類型的指針(從進程的非托管內存中分配內存)
IntPtr paramPtr = Marshal.AllocHGlobal(Marshal.SizeOf(typeof(SEG2)));
//將字節數組復制到指針
Marshal.Copy(fileByte, 0, paramPtr, Marshal.SizeOf(typeof(SEG2)));
////將指定的指針轉為特定類型的對象(將數據從非托管內存塊封送到新分配的指定類型的托管對象)
SEG2 obj = (SEG2)Marshal.PtrToStructure(paramPtr, typeof(SEG2));
  1. 將對象從托管對象復制到內存塊
//將對象復制給指針所指內存
var obj=new object();
Marshal.StructureToPtr(obj, paramPtr, true);
  1. 釋放內存,內存在非托管塊需要手動釋放

            Marshal.FreeHGlobal(paramPtr);
  1. 復雜對象
    如果為數組這類非固定位數的對象,可以通過多次調用的方式依次將托管對象與非托管對象互相轉換
    形式上更像c/c++利用指針對內存進行操作


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM