【问题标题】:Swift missing property from C Flexible Array Member in Struct?Struct中C灵活数组成员的Swift缺少属性?
【发布时间】:2020-09-01 12:48:58
【问题描述】:

我遇到了与here 解释的完全相同的问题。不幸的是,我不明白究竟是什么改变来解决这种情况。 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。

【问题讨论】:

  • 您链接的问题的答案及其上的 cmets 表明选择的解决方案是声明成员数组的大小,使其不再是 FAM。我不相信 OP 或那里的回答者完全理解发生了什么,但将 FAM 更改为普通数组成员可以解决问题也就不足为奇了。
  • 我对 Swift 不太熟悉,尤其是它的 C 互操作功能,但如果它根本不提供对 FAM 的访问,我不会感到惊讶,至少不提供对 FAM 的访问。我没有看到任何通用的方法来做到这一点。

标签: c swift pointers memory c99


【解决方案1】:

我还没有找到解决此问题的正确方法,但如果它从未得到回答,我确实找到了解决方法。我可以访问 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)
    }
}

【讨论】:

  • 我的建议是避免使用 FAM。它们在纯 C 中使用起来非常棘手,并且在混合中添加另一种语言似乎需要额外的帮助。在问题中提出的特定情况下,我建议使用指向消息正文的普通指针,并将大小作为单独的随附参数传递。这在 C 方面会更惯用,我预测它会更适合您。
  • 感谢您的反馈。我忘了提到随后的调用需要一个类型化的指针,这就是为什么我从一开始就没有使用原始指针。
猜你喜欢
  • 2020-12-30
  • 1970-01-01
  • 2011-03-04
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2020-07-25
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多