Playing with raw data in Swift I came across something I don't understand.
NSData has a constructor:
init(bytes: UnsafePointer<Void>, length: Int)
where the first bytes parameter is clearly of UnsafePointer type.
However, if I pass [Byte] object to this constructor, not only does the compiler not complain, but it works ok.
But if I try to cast [Byte] to UnsafePointer, I fail.
How does this work?
For example (you can try it in Playgrounds):
let buffer: [Byte] = [0x00, 0xff]
let data = NSData(bytes: buffer, length: buffer.count) // no error
data.description
var pointer: UnsafePointer<Void>
// comment this line to avoid compiler error
pointer = buffer // error
I know I can do
UnsafePointer<Void>(buffer)
but my question is, what does NSData constructor do implicitly, that I don't have to do that.
Swift maps its own types to C pointers when you're calling a C function that requires them. Apple has a bit of documentation on this interaction: Interacting with C APIs.
In short, when you're calling a function that takes an UnsafePointer<Type>
, it can accept nil
, an inout
variable of that type, an array of that type (i.e., [Type]
, what you're using), or one of the generic Swift pointer types. A function taking UnsafePointer<Void>
can take any of those, with no constraint on the type at all, so you need to read the function's documentation to see what it expects/will return.