使用Swift,如何将UUID传递给带有uuid_t的C函数?
假设我在桥接标题中声明了以下函数:
bool my_set_uuid(uuid_t uuid);
在Swift中,我试图传递一个新的UUID:
let uuid = UUID()
my_set_uuid(uuid.uuid)
我收到以下错误:“无法转换类型'uuid_t'(又名'(UInt8,UInt8,UInt8,UInt8,UInt8,UInt8,UInt8,UInt8,UInt8,UInt8,UInt8,UInt8,UInt8,UInt8, UInt8,UInt8)')预期的参数类型'UnsafeMutablePointer!'“
我知道这是因为UUID.uuid的类型为uuid_t,它实现为16字节的C数组,在Swift中成为16个UInt8的元组。但为什么我不能将C uuid_t传递给C?它似乎在期待一个指针。
所以,我尝试用withUnsafeMutableBytes创建指向我的uuid的指针。我发现这很有效:
let _: UInt8 = withUnsafeMutablePointer(to: &uuid.0) { ptr in
my_set_uuid(ptr)
return 0
}
但是我也读过& uuid.0是不安全的,因为我在我的C函数中使用了整个元组(作为一个数组)。此外,我与let _: UInt8
和return 0
所做的所有装扮似乎都是错误的。
答案 0 :(得分:2)
以这种方式使用&uuid.0
确实不安全。由于Swift编译器可以在临时区域中创建单个元素的副本,并将该区域的地址传递给该函数。这可能不会在优化代码中发生,但您无法预测Swift生成的代码。
为了使您的代码安全,您可能需要编写如下内容:
let uuid = UUID()
var rawUuid = uuid.uuid
// (You can rewrite the two lines above into a sigle line as `var rawUuid = UUID().uuid`
let result = withUnsafeMutablePointer(to: &rawUuid) {uuidPtr in
uuidPtr.withMemoryRebound(to: UInt8.self, capacity: MemoryLayout<uuid_t>.size) {bytePtr in
my_set_uuid(bytePtr)
}
}
(result
获取my_set_uuid(bytePtr)
的值。如果您想忽略该结果,请将let result
替换为_
。)
uuid_t
是C中固定大小的数组类型,这在Swift中很难处理。也许Swift中的元组类型应该有更好的方法来处理这种用例。
答案 1 :(得分:-1)
你可以试试这个:
let uuid = UUID().uuidString
_ = uuid.withCString { s1 in
my_set_uuid(UnsafeMutablePointer(mutating: s1))
}