The auto-generated Swift 5 interface is defined as follows:
open class Writer : NSObject {
open func writeUUID(_ value: UnsafeMutablePointer<UInt8>)
}
Example of trying to create a UUID and then passing its uuid_t to an Objective-C class:
let uuid = UUID().uuid
// Error: Cannot convert value of type 'UnsafeMutablePointer<_>'
// to expected argument type 'UnsafeMutablePointer<UInt8>'
withUnsafeMutablePointer(to:u) {
encoder.writeUUID($0)
}
// Error: Cannot convert value of type '(UnsafeMutablePointer<UInt8>) -> Void'
// to expected argument type '(UnsafeMutablePointer<_>) -> _'
withUnsafeMutablePointer(to:u) { (ptr:UnsafeMutablePointer<UInt8>) in
encoder.writeUUID(ptr)
}
How can I pass a uuid_t from Swift to Objective-C and back?
I'm prettty sure this is safe, though admittedly I'm never 100% certain when to use withMemoryRebound(to:) and friends. @Andrew_Trick can probably confirm or deny:
import Foundation
var uuid = UUID().uuid
withUnsafeMutablePointer(to: &uuid) { tuplePointer in
tuplePointer.withMemoryRebound(to: UInt8.self, capacity: 1) { pointer in
uuid_generate(pointer)
}
}
(I used uuid_generate in my example instead of your Obj-C API in order to have a self-contained example for testing.)
Unfortunately, withMemoryRebound(to:) requires that the pointer's Pointee and the destination type be the same size, which doesn't work with this tuple -> element conversion. I think you need to round-trip through UnsafeRawPointer(tuplePointer).assumingMemoryBound(to: UInt8.self) in this case.
That’s unnecessary: we can use withUnsafeBytes(of:) instead of withUnsafePointer(to:).
import Foundation
var uuid = UUID().uuid
withUnsafeBytesOf(of: &uuid) { pointer in
uuid_generate(pointer.baseAddress)
}
If it is truly necessary to get UnsafePointer<UInt8> instead of UnsafeRawPointer (and I strongly recommend trying with the raw pointer first), then you can safely use assumingMemoryBound here. This is more or less the only case where it’s safe: the memory is already UInt8s, so you aren’t violating the aliasing rules by accessing it that way.
@nnnnnnnn@lukasa Thanks for correcting me. UnsafeRawPointer doesn't match the API @kennyc is trying to call (or uuid_generate), so a working solution would be this:
import Foundation
var uuid = UUID().uuid
withUnsafeMutableBytes(of: &uuid) { rawPointer in
// Force unwrap is safe because we know rawPointer.count > 0
let typedPointer = rawPointer.baseAddress!.assumingMemoryBound(to: UInt8.self)
uuid_generate(typedPointer)
}