【问题标题】:Large C array not imported in Swift 5.2Swift 5.2 中未导入大型 C 数组
【发布时间】:2021-03-18 15:16:52
【问题描述】:

我正在尝试导入一个 64kb 的 C 数组,作为设备上日志的循环缓冲区。当我尝试在 Swift 中访问这个数组时,我遇到了错误

“记录”类型的值没有成员“数据”

为了尝试回答有关桥接的潜在问题,我使用了导入的 C 库中的其他类型,这些类型定义在该模拟代码所源自的同一文件中。

代码设置如下:

logging.h:

typedef struct _logging {
    uint8_t data[64*1024];
} logging;

ReadLog.swift:

struct ReadLog {
    var log: logging = logging()

    func read() {
        //...Do some stuff...
        let char = log.data.0 // <- Error here 'Value of type 'logging' has no member 'data'
    }
}

将数据大小更改为 256 导入此成员没有问题。 (我不知道截止点是多少)。

处理这个问题的最佳方法是什么?

【问题讨论】:

  • 我认为你的log 变量应该是一个指针,看这个:stackoverflow.com/questions/24050942/swift-use-c-struct
  • 谢谢,我试试看。
  • 头文件里面有什么? Swift 看不到标题中没有的内容。我不认为它必须是一个指针。
  • @Sulthan 我已将示例更新为标题。

标签: c swift


【解决方案1】:

问题是 C 数组作为元组导入到 Swift 中,并且元组具有最大数量(例如参见 What is the limit (if any) to the tuple cardinality in Swift?)。 Swift 5 中的当前限制似乎是 4096 个元组元素。

一种可能的解决方法是创建一个 C 辅助函数,该函数返回指向 C 数组的指针。使用SE-0044 Import as member 功能,它可以看起来像一个 Swift 属性。

您只需在定义logging 结构的C 头文件或桥接头文件中添加以下代码:

// Pointer to the data elements:
__attribute__((swift_name("getter:logging.dataPtr(self:)")))
static inline const uint8_t * _Nonnull loggingDataPtr(const logging * _Nonnull log)
{
    return log->data;
}

现在您可以通过指针读取 Swift 代码中的日志数据:

struct ReadLog {
    var log = logging()

    func read() {
        //...Do some stuff...
        let char = log.dataPtr[0]
    }
}

但请注意,没有数组边界检查,您必须确保 log.dataPtr 仅与数组大小内的索引一起使用。

如果你想从 Swift 读取 并写入 到日志结构,那么将辅助函数更改为

// Pointer to the data elements:
__attribute__((swift_name("getter:logging.dataPtr(self:)")))
static inline uint8_t * _Nonnull loggingDataPtr(logging * _Nonnull log)
{
    return log->data;
}

【讨论】:

  • 感谢您提供这些信息,它帮助很大!
猜你喜欢
  • 2016-08-17
  • 1970-01-01
  • 1970-01-01
  • 2015-10-04
  • 1970-01-01
  • 2014-09-17
  • 2016-10-21
  • 1970-01-01
  • 2016-12-17
相关资源
最近更新 更多