The C array char name[8]
is imported to Swift as a tuple:
(Int8, Int8, Int8, Int8, Int8, Int8, Int8, Int8)
The address of name
is the same as the address of name[0]
, and
Swift preserves the memory layout of structures imported from C, as
confirmed by Apple engineer Joe Groff:
… You can leave the struct defined in C and import it into Swift. Swift will respect C’s layout.
As a consequence, we can pass the address of record.name
,
converted to an UInt8
pointer, to
the String initializer. The following code has been updated for Swift 4.2 and later:
let record = someFunctionReturningAStructRecord()
let name = withUnsafePointer(to: record.name) {
$0.withMemoryRebound(to: UInt8.self, capacity: MemoryLayout.size(ofValue: $0)) {
String(cString: $0)
}
}
NOTE: It is assumed that the bytes in name[]
are a valid NUL-terminated UTF-8 sequence.
For older versions of Swift:
// Swift 2:
var record = someFunctionReturningAStructRecord()
let name = withUnsafePointer(&record.name) {
String.fromCString(UnsafePointer($0))!
}
// Swift 3:
var record = someFunctionReturningAStructRecord()
let name = withUnsafePointer(to: &record.name) {
$0.withMemoryRebound(to: UInt8.self, capacity: MemoryLayout.size(ofValue: record.name)) {
String(cString: $0)
}
}