我正在尝试导入一个64kb的C数组,该数组旨在作为设备上日志的循环缓冲区。当我试图在Swift中访问这个数组时,我遇到了错误
"logging"类型的值没有成员"data">
为了回答有关桥接的潜在问题,我正在使用导入的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导入了此成员,没有任何问题。(我不知道截止日期是多少(。
处理这个问题的最佳方法是什么?
问题是,C数组作为元组导入Swift,并且元组具有最大arity(例如,请参阅Swift中元组基数的限制(如果有的话(是多少?(。Swift 5中的当前限制似乎是4096个元组元素。
一个可能的解决方法是创建一个C辅助函数,该函数返回一个指向C数组的指针。通过SE-0044作为成员导入功能,可以使其看起来像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读取并将写入日志结构,则将helper函数更改为
// Pointer to the data elements:
__attribute__((swift_name("getter:logging.dataPtr(self:)")))
static inline uint8_t * _Nonnull loggingDataPtr(logging * _Nonnull log)
{
return log->data;
}