John Scalo John Scalo - 2 months ago 121
Swift Question

Converting C array ptr to native array in Swift 3

I have a ptr from a C library that points to an array of Floats. Its type is UnsafeMutablePointer. How do I create a native [Float] array from this in Swift 3?

Here's what I'm trying:

var reconstructedFloats = [Float](repeatElement(0, count: size))
reconstructedFloats.withUnsafeMutableBufferPointer {
let reconstructedFloatsPtr = $0
print(type(of:$0)) // "UnsafeMutableBufferPointer<Float>"
cFloatArrayPtr?.withMemoryRebound(to: [Float].self, capacity: size) {
UnsafeMutableRawPointer(reconstructedFloatsPtr.baseAddress!).storeBytes(of: $0.pointee, as: Float.self)
}

UnsafeMutableRawPointer(reconstructedFloatsPtr.baseAddress!).storeBytes(of: (cFloatArrayPtr?.pointee)!, as: Float.self)
}


That seems insanely overcomplicated so hopefully there's an easy way, but even this code produces a compile error:
Type of expression is ambiguous without more context
.

If you want to plug it into a playground, here's a complete sample that contrives the cFloatArrayPtr:

// Let's contrive a C array ptr:
var size = 3
var someFloats: [Float] = [0.1, 0.2, 0.3]
var cFloatArrayPtr: UnsafeMutablePointer<Float>?

someFloats.withUnsafeMutableBufferPointer {
cFloatArrayPtr = $0.baseAddress
}

print(type(of:cFloatArrayPtr!)) // "UnsafeMutablePointer<Float>"

var reconstructedFloats = [Float](repeatElement(0, count: size))
reconstructedFloats.withUnsafeMutableBufferPointer {
let reconstructedFloatsPtr = $0
print(type(of:$0))
cFloatArrayPtr?.withMemoryRebound(to: [Float].self, capacity: size) {
UnsafeMutableRawPointer(reconstructedFloatsPtr.baseAddress!).storeBytes(of: $0.pointee, as: Float.self)
}

UnsafeMutableRawPointer(reconstructedFloatsPtr.baseAddress!).storeBytes(of: (cFloatArrayPtr?.pointee)!, as: Float.self)
}

print(reconstructedFloats)

Answer

You can make an UnsafeBufferPointer from your pointer. UnsafeBufferPointer is a Sequence, so you can directly make an array from it:

let buffer = UnsafeBufferPointer(start: cFloatArrayPtr, count: size)
var reconstructedFloats = Array(buffer)

Of course, this creates a copy.

Comments