C#模拟union接收

field Offset属性

单片机发送浮点数数采用联合体数据转化好像挺高效的(目前的使用中并没有太深入了解高效、内存等问题),C#中没有联合体的数据类型,可以通过使用特性可以自定义结构在内存中的布局方式,即通过一定的方式直接指定位置偏移量,以创建在 C/C++ 中称为联合的布局。 此时需引用程序集 :using System.Runtime.InteropServices;
[StructLayout(LayoutKind.Explicit)]
public struct union //union只是自己起的名字
{
   [FieldOffset(0)] /作为数据头使用
   public byte temple0;
   
   [FieldOffset(1)]
   public byte temple1;
   [FieldOffset(2)]
   public byte temple2;
   [FieldOffset(3)]
   public byte temple3;
   [FieldOffset(4)]
   public byte temple4;
   
   [FieldOffset(5)]
   public byte temple5;
   [FieldOffset(6)]
   public byte temple6;
   [FieldOffset(7)]
   public byte temple7;
   [FieldOffset(8)]
   public byte temple8;
   
   [FieldOffset(9)]  //作为数据尾使用
   public byte temple9;
   
   [FieldOffset(1)]  //偏移量回归
   public float dataGPSLng;
   [FieldOffset(5)]
   public float dataGPSLat;
}

 - [StructLayout(LayoutKind.Explicit)]

LayoutKind 是一个枚举类型,有 Auto、 Explicit、 Sequential三种,它和 StructLayoutAttribute 一起使用; 默认情况下,公共语言运行库(common language runtime)使用的是Auto, 而C#, Visual Basic, and C++ compilers 为减少Auto的错误,对于结构 默认使用Sequential,而对于类,顺序布局则必须显示指明LayoutKind.Sequential;
Explicit: 精确布局
** 需要用FieldOffset() 设置 每个成员 的位置, 这样就可以实现类似c的公用体的功能;

Sequential: 顺序布局
** 即先排完前一个在紧接着拍下一个,两个地址差为前者的字节长;因为C#默认使用这个,使用加不加效果一样的;

StructLayout
/* [StructLayout(LayoutKind.Explicit, Size=16, CharSet=CharSet.Ansi)] */

StructLayout : 结构布局属性, 允许自己控制内存中类或结构的数据字段的物理布局;支持三种可选字段:CharSet、 Pack、Size;
CharSet :目前没用到,不写了,,
Size:指示类或结构的绝对大小;
Pack:控制内存中类或结构的数据字段的对齐方式;它同时影响顺序和精确布局,其值必须为0、1、2、4、8、16、32、64或 128;默认情况下值为0,指示当前平台的默认包装大小;因为自己写的时候是规定了每一个字节,所以内存对齐了,要是不对齐要看看官网:
https://docs.microsoft.com/en-us/dotnet/api/system.runtime.interopservices.structlayoutattribute.pack?view=netframework-4.7.2

Tips:
** 在使用这个时本来想用数组和float的,但是报错说值类型与引用类型在这里不能同时引用,(类(数组为类)为引用类型,而结构为值类型), 后来搜是有办法让数组类型和普通值类型的共存的办法(没有测试过)
https://www.cnblogs.com/chihirosan/archive/2016/01/28/5166057.html

..............调用...........
        private delegate void ReceiveGPSDataDelagate(float longitude, float latitude);  
        private ReceiveGPSDataDelagate receiveGPSDataDelagate;
................
   union reData = new union();
   byte[] ReDatasTemp = new byte[10]; //用于先存储一次发过来的数据, byte即是无符号整型
   Port.Read(ReDatasTemp, 0, ReDatasTemp.Length);
    if ((ReDatasTemp[0] == 0x65) && (ReDatasTemp[9] == 0x66)) 
       {
         reData.temple1 = ReDatasTemp[1];
         reData.temple2 = ReDatasTemp[2];
         reData.temple3 = ReDatasTemp[3];
         reData.temple4 = ReDatasTemp[4];
        
         reData.temple5 = ReDatasTemp[5];
         reData.temple6 = ReDatasTemp[6];
         reData.temple7 = ReDatasTemp[7];
         reData.temple8 = ReDatasTemp[8];
         
         receiveGPSDataDelagate = new ReceiveGPSDataDelagate(ChangeGPSText);    //实例化委托类型变量
         Dispatcher.Invoke(receiveGPSDataDelagate, reData.dataGpsLng, reData.dataGpsLat); //调用异步线程
        }
  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值