zoukankan      html  css  js  c++  java
  • 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++利用指针对内存进行操作
  • 相关阅读:
    [转] 浅谈 C++ 中的 new/delete 和 new[]/delete[]
    [转] dpkg-deb命令
    [转] 将DOS格式文本文件转换成UNIX格式
    STM32与FreeRTOS实现低功耗
    设置Beyond Compare 为 Git 默认的比较工具
    [转]Linux进程间通信——使用消息队列
    还你一个自由、干净的网络环境
    Linux下的Hello world
    Cortex-M3中C与汇编的交互
    数据结构25:矩阵转置算法(三元组顺序表)
  • 原文地址:https://www.cnblogs.com/ives/p/14248409.html
Copyright © 2011-2022 走看看