首页 > 解决方案 > 结构中的 C 灵活数组成员中的 Swift 缺少属性?

问题描述

我遇到了与此处解释的完全相同的问题。不幸的是,我不明白究竟做了什么改变来解决这种情况。OP 是否提示 Swift 灵活数组成员的大小以使其在 Swift 中可见?OP是否修改了C库?我想避免这样做。

我在 Swift 中使用了一个 C 库,它返回一个带有灵活数组成员“mbody”的结构。

typedef struct {
    size_t size;
    char mbody[];
} msg

在 Swift 中,当返回这个结构时,我可以访问属性“size”,但不能访问属性“mbody”。我已经确认 mbody 设置正确。初始化 C 结构的代码的简化版本如下:

    const size_t mem_size = msgcount * MSGBOX_SIZE;
    msg* ret = malloc(sizeof(msg) + mem_size);

    if (!ret)
        return NULL;

    ret->size = mem_size;
    memcpy(ret->mbody, msgrecord, MSGBOX_SIZE);

为什么 Swift 没有获取 msg->mbody 的大小?它是编译器设置吗?我将其设置为 C99。

标签: cswiftpointersmemoryc99

解决方案


我还没有找到解决这个问题的正确方法,但如果它从未得到回答,我确实找到了解决方法。我可以访问 ret 的指针并通过使用 ret->size 读取完整的内存,然后推进 mem_size 的大小。我意识到那里可能有一个正确的解决方案,而这个可能还有一个额外的不必要的步骤(提前),但我还想不通。

let size = retPointer.pointee.size
let msgRaw = Data(bytes: retPointer, count: (MemoryLayout<msg>.stride + size))
let msgBody = msgRaw.advanced(by: MemoryLayout<Int>.stride) 

相反,我的解决方法并不漂亮但有效。我仍然很感激任何能够展示在 Swift 结构中处理 C 灵活数组成员的正确方法的人。在我的解决方法中,我计算需要多少 msg 对象来创建一个足够长的缓冲区以供正文使用,然后复制到该空间。

let totalmem = (mem_size + MemoryLayout<Int>.stride) / MemoryLayout<msg>.stride
let max = Int(ceil(Double(totalmem)) + 1.0)
withUnsafeMutablePointer(to: &msgObj) { orderPtr in
    orderPtr.withMemoryRebound(to: msg.self, capacity: max){ reboundPtr in
        let bodyPtr = UnsafeMutableRawPointer(reboundPtr).advanced(by: MemoryLayout<Int>.stride)
        let bodyBufferPtr = UnsafeMutableRawBufferPointer(start: bodyPtr, count: mem_size)
        body.copyBytes(to: bodyBufferPtr)
    }
}

推荐阅读