Flutter项目中Dart如何实现类似C++的对象内存字节表示获取?
在Dart中实现适配Arduino的结构体内存字节转换
可以实现,但Dart没有C++那种直接取对象内存地址转字节的底层机制,需要通过手动序列化/反序列化模拟,核心是严格对齐Arduino端结构体的内存布局(包括数据类型长度、字节序、内存对齐规则),确保两端字节流完全一致。
步骤1:定义Dart对应数据结构
先把Arduino的MessageHeaderData结构体映射为Dart类,同时匹配Arduino的基础数据类型:
// 对应Arduino的unsigned char typedef Byte = int; // 对应Arduino的unsigned short int typedef Short = int; // 模拟Arduino的IP类型(假设是4字节IPv4) class IP { final List<Byte> octets; IP(this.octets) : assert(octets.length == 4, "IP必须是4个字节"); } // 匹配Arduino的MessageType枚举(需确保Arduino端声明为unsigned char类型) enum MessageType { hello, data, ack } // 对应Arduino的MessageHeaderData结构体 class MessageHeaderData { Byte protocol; IP source; IP destination; MessageType messageType; Byte checksum; Short sizeOfPayload; Byte numberOfHops; MessageHeaderData({ required this.protocol, required this.source, required this.destination, required this.messageType, required this.checksum, required this.sizeOfPayload, required this.numberOfHops, }); }
步骤2:实现序列化(Dart对象转字节数组)
按照Arduino结构体的字段顺序和内存布局,逐个字段转成字节:
extension MessageHeaderSerializer on MessageHeaderData { List<int> toBytes() { final buffer = BytesBuilder(); // 1. protocol (1字节) buffer.addByte(protocol); // 2. source IP (4字节) buffer.add(source.octets); // 3. destination IP (4字节) buffer.add(destination.octets); // 4. messageType (枚举索引转1字节,需确保Arduino端枚举是unsigned char) buffer.addByte(messageType.index); // 5. checksum (1字节) buffer.addByte(checksum); // 6. sizeOfPayload (2字节,小端序,匹配Arduino默认字节序) final sizeBuffer = Uint16List(1)..[0] = sizeOfPayload; buffer.add(sizeBuffer.buffer.asUint8List()); // 7. numberOfHops (1字节) buffer.addByte(numberOfHops); return buffer.toBytes(); } }
步骤3:实现反序列化(字节数组转Dart对象)
反向解析字节流,还原为Dart对象:
extension MessageHeaderDeserializer on List<int> { MessageHeaderData toMessageHeader() { // 先校验总字节数,需和Arduino端sizeof(MessageHeaderData)一致 const expectedLength = 1 + 4 + 4 + 1 + 1 + 2 + 1; // 共14字节(需根据Arduino实际值调整) if (length != expectedLength) { throw ArgumentError("字节长度不匹配,预期$expectedLength,实际$length"); } var offset = 0; // 1. 解析protocol final protocol = this[offset++]; // 2. 解析source IP final sourceIP = IP(sublist(offset, offset += 4)); // 3. 解析destination IP final destIP = IP(sublist(offset, offset += 4)); // 4. 解析messageType final msgType = MessageType.values[this[offset++]]; // 5. 解析checksum final checksum = this[offset++]; // 6. 解析sizeOfPayload(小端序转short) final sizeBytes = Uint8List.fromList(sublist(offset, offset += 2)); final sizeOfPayload = Uint16List.view(sizeBytes.buffer)[0]; // 7. 解析numberOfHops final numberOfHops = this[offset++]; return MessageHeaderData( protocol: protocol, source: sourceIP, destination: destIP, messageType: msgType, checksum: checksum, sizeOfPayload: sizeOfPayload, numberOfHops: numberOfHops, ); } }
关键注意事项
- 内存对齐校验:先在Arduino中打印
sizeof(MessageHeaderData)的实际值,调整Dart代码中的expectedLength,避免编译器自动对齐导致的字节数差异。 - 字节序匹配:Arduino默认是小端序,如果你的硬件是大端架构,需要手动反转
sizeOfPayload的字节顺序。 - 枚举类型一致性:Arduino端的
MessageType必须声明为enum MessageType : unsigned char { ... };,确保枚举值是单字节,和Dart端的索引映射一致。
内容的提问来源于stack exchange,提问作者Chris
相关产品推荐
相关产品推荐

