You're making pointers to the contents of Arrays, and then those arrays immediately get deallocated because they're not referenced anymore. The Array-to-pointer conversion is also only valid for the duration of the call where the Array is passed as an argument…which in this case is the call to UnsafePointer's initializer. (We have an open bug to add a warning for this kind of code.)
There's not a great way to safely build C arrays of pointers to C arrays from a Swift Array-of-Arrays; the best I could come up with involves manually allocating some C arrays and cleaning them up afterwards.
let distances: [UnsafeMutableBuffer<Int64>] = self.distanceResponse.distances.map {
let buffer = UnsafeMutableBuffer<UInt64>.allocate(capacity: $0.count)
buffer.initialize(from: $0.lazy.map { Int64($0) })
return buffer
}
defer {
distances.forEach { $0.deallocate() }
}
// similar for "durations"
distances.withUnsafeBufferPointer { distancesBuffer in
durations.withUnsafeBufferPointer { durationsBuffer in
assert(distancesBuffer.count == durationsBuffer.count)
var s = RoutingData(
locationsCount: Int32(distancesBuffer.count),
distanceMatrix: distancesBuffer.baseAddress
durationMatrix: durationsBuffer.baseAddress)
Solve(&s)
}
}
That's a lot messier, to be sure, but it makes all the lifetimes explicit.
Thank you for your reply!
I will definitely try your solution tomorrow.
What do you mean about manually allocating C arrays? Function that takes size of array allocate array and return pointer (**) to Swift?
I'm referring to the use of UnsafeMutableBuffer<UInt64>.allocate (and only thinking about a single level of pointer here). If you had a single-dimensional array, I'd suggest just using Swift's Array type, which (as shown for the top-level arrays) can provide a pointer to its contents within a bounded scope.* But since you can't get pointers to every sub-Array of a top-level Array in this way, I gave up on trying to use Array for the inner arrays, and instead allocated my own memory.
* Swift.Array also supports being implicitly converted to a pointer when used as an argument, but the pointer isn't guaranteed to be valid after the call is over, so it's only useful as a shorthand for the bounded scope version