【发布时间】:2019-11-21 19:22:43
【问题描述】:
我正在尝试将现有的 C 库连接到 iOS 上的 Swift 5.0.1 代码。 C 头文件有以下定义:
char hostname[SFL_MAX_HOSTNAME_CHARS+1];
char os_release[SFL_MAX_OSRELEASE_CHARS+1];
int readHidCounters(HSP *sp, SFLHost_hid_counters *hid, char *hbuf, int hbufLen, char *rbuf, int rbufLen);
typedef struct _HSP {
[Many other elements omitted for brevity]
char hostname[SFL_MAX_HOSTNAME_CHARS+1];
char os_release[SFL_MAX_OSRELEASE_CHARS+1];
} HSP;
readHidCounters 有一个实现(为简洁起见):
int readHidCounters(HSP *sp, SFLHost_hid_counters *hid, char *hbuf, int hbufLen, char *rbuf, int rbufLen) {
int gotData = NO;
size_t len = hbufLen;
if(sysctlbyname("kern.hostname", hbuf, &len, NULL, 0) != 0) {
myLog(LOG_ERR, "sysctl(<kern.hostname>) failed : %s", strerror(errno));
}
else {
gotData = YES;
hid->hostname.str = hbuf;
hid->hostname.len = strlen(hbuf);
}
// UUID
memcpy(hid->uuid, sp->uuid, 16);
[...]
}
我创建了一个 HSP 结构并尝试像这样在 Swift 中调用 readHidCounters
var sp = HSP()
[...]
readHidCounters(&sp,
&hidElem.counterBlock.host_hid,
&sp.hostname, // This is the error line
SFL_MAX_HOSTNAME_CHARS,
&sp.os_release,
SFL_MAX_OSRELEASE_CHARS)
我试图传入&sp.hostname 导致编译器错误Cannot convert value of type '(Int8, Int8, Int8, [...], Int8)' to expected argument type 'Int8'。问题是主机名是 Int8 的元组,我似乎无法将其正确转换为 char *。我尝试了UnsafeMutablePointer、withUnsafeMutablePointer 的各种化身,但看不到如何正确识别hostname。任何建议都非常感谢!
[已解决]
MartinR 几乎用他的建议解决了这个问题,但它确实存在编译器错误:Overlapping accesses to 'sp.hostname', but modification requires exclusive access; consider copying to a local variable。编译的更新代码是
var myHostName = sp.hostname
var myOsRelease = sp.os_release
let _ = withUnsafeMutablePointer(to: &myHostName) {
$0.withMemoryRebound(to: Int8.self, capacity: MemoryLayout.size(ofValue: sp.hostname)) {
hostNamePtr in
withUnsafeMutablePointer(to: &myOsRelease) {
$0.withMemoryRebound(to: Int8.self, capacity: MemoryLayout.size(ofValue: sp.os_release)) {
osReleasePtr in
readHidCounters(&sp,
&hidElem.counterBlock.host_hid,
hostNamePtr, SFL_MAX_HOSTNAME_CHARS,
osReleasePtr, SFL_MAX_OSRELEASE_CHARS)
}
}
}
}
【问题讨论】:
-
API 对我来说不是很清楚。如果 hostname 和 os_release 是 HSP 结构的一部分(作为第一个参数传递给函数),那么为什么还要将这些数组作为参数传递给函数呢?
-
@MartinR 我已经添加了
readHidCounters的部分实现。你说的是真的,可能实现者不想跟sp这么紧密的耦合? -
也许我不熟悉那个库。 – 我提出了一些建议,但我只能验证它是否编译, 而不是它适用于你的情况。