将 Swift 结构转换为数据字节

Posted

技术标签:

【中文标题】将 Swift 结构转换为数据字节【英文标题】:Convert Swift struct to Data bytes 【发布时间】:2020-10-19 18:20:31 【问题描述】:

我想以蓝牙固件所期望的格式将字节数据传递给蓝牙服务。

c struct 中的预期数据结构是:

typedef enum 
        CMD_TX_INFO = 0,
        CMD_DATA_REQ_START,
        CMD_DATA_REQ_END,
        CMD_DATA_REQ
 ble_cmd_type_t;

typedef struct ble_data_info_s

        uint32_t data_size_bytes;
        uint32_t info;
 ble_data_info_t;

typedef PACKED ( struct ble_cmd_info

        ble_cmd_type_t  cmd_type;
        ble_data_info_t info;
        uint8_t len;
        uint8_t data[10];
) ble_cmd_data_t;

我已将 this 转换为 swift 结构,如下所示:

enum BLECmdType : UInt8
    case CMD_TX_INFO = 0
    case CMD_DATA_REQ_START
    case CMD_DATA_REQ_END
    case CMD_DATA_REQ


struct BLEDataInfo

    let dataSizeBytes: UInt32
    let info: UInt32


struct BLECmdData

    let cmdType:BLECmdType 
    let info:BLEDataInfo
    let len:UInt8
    let data: Array<UInt8>?

然后我将 swit struct 对象转换成这样的字节,我不确定这种方法是否正确?我没有得到正确的预期格式的字节:

var command = BLECmdData(cmdType:BLECmdType.CMD_DATA_REQ_START, 
    info: BLEDataInfo(dataSizeBytes: 100000, info: 10), 
    len: 1, 
    data: [1,2,3,4,5,6,7,8,9,10])

let bleData = Data(bytes: &command , count: MemoryLayout<BLECmdData>.stride)
        

首先是否可以以字符串格式打印为 bleData 对象生成的字节,以便我可以调试和查看?

其次发送到BLE设备的字节是:

Bytes:
01 00 00 00 A0 86 01 00
E5 73 E0 98 0A 00 00 00
70 C5 CA 80

提到的固件工程师,数据应该从以下开始:

Bytes:
01 00 A0 86 01 00
E5 73 E0 98

我不确定我在这里将 c struct 转换为 swift 的方法是否正确。

期待您的回复。

谢谢

【问题讨论】:

***.com/questions/39075043/… 你必须知道字节序、对齐、填充......让我在答案中解释 我知道无法以与 C 结构兼容的方式自动将 Swift 结构转换为字节。您必须手动枚举结构的字段并将每个字段单独转换为所需格式的字节 我会保留 C 结构。 Swift Struct 和 C Struct 之间的“匹配”不一定相同,不是吗? 【参考方案1】:
    行的结果 let bleData = Data(bytes: &amp;command , count: MemoryLayout&lt;BLECmdData&gt;.stride)

这取决于您正在运行的程序的 cpu 架构。 (32 位与 64 位,大端与小端)。

    您必须向Firmware engineer 询问与他们的设备通信的协议,然后您会将数据编码为协议中指定的格式。将数据存储在类/结构/枚举等中并不重要,重要的是数据的编码方式。

【讨论】:

或者至少你可以要求他们提供一些PACKED和对应的编码数据。【参考方案2】:

我找到了一种以正确格式成功推送数据的方法:

设置值:

var cmdTypeCopy:UInt8 = BLECmdType.CMD_DATA_REQ_START
var imageInfo = BLEDataInfo(dataSizeBytes: 100000, info: 10)
var cmdLenCopy = 10
var cmdDataCopy:Array<UInt8> = [1,2,3,4,5,6,7,8,9,10]

创建数据:

var cmdTypeData = Data(bytes: &cmdTypeCopy, count: MemoryLayout<UInt8>.stride)
var imageInfoData = Data(bytes: &imageInfo, count: MemoryLayout<BLEImageInfo>.stride)
var cmdLenData = Data(bytes: &cmdLenCopy, count: MemoryLayout<UInt8>.stride)
var cmdDataData = Data(bytes: &cmdDataCopy, count: 10)

然后一一追加:

cmdTypeData.append(imageInfoData)
cmdTypeData.append(cmdLenData)
cmdTypeData.append(cmdDataData)

这非常有效,固件以正确的格式获取数据。

【讨论】:

以上是关于将 Swift 结构转换为数据字节的主要内容,如果未能解决你的问题,请参考以下文章

如何将json数据转化为数据库文件

将 CSV 解析为数据网格 WinForms

java实现解析二进制文件

为数据网格视图选择不同的连接字符串

将元组条目变量转换为数学问题的 int 的问题

在python中重写wav文件的问题