1

I'm trying to convert a UInt16 array to an UnsafeMutablePointer<UInt16> in order to call a C function that takes a uint16_t * from Swift.

If my starting point were [UInt8], and my destination UnsafeMutablePointer<UInt8>, it would all be easy. I could convert the array to Data, from there to NSData, call bytes.assumingMemoryBound, and with that I'd be (almost) done.

However, with the task at hand, there are a couple different paths I'm considering. One approach is converting the [UInt16] to [UInt8], go the same data path as described above, and then specify a different type in the assumingMemoryBound call.

That is proving to be more involved than anticipated, though. There are a bunch of questions on how to convert an array of just two UInt8s to one UInt16; I have found one question asking how to convert a single UInt16 to two UInt8s, but it all seems to be getting much more involved when converting arrays.

The other approach I'm trying is to simply take the [UInt16] array value and try converting it to an UnsafeMutablePointer<UInt16> using an intermediate withUnsafeBytes call or something of that sort, but Swift has a bunch of different pointer types that just won't match up. Specifically, here's one of my earlier attempts:

array.withUnsafeBytes { (pointer: UnsafeRawBufferPointer) -> UnsafeMutablePointer<UInt16> in
    let mutablePointer = UnsafeMutablePointer<UInt16>(mutating: pointer) // error
    return mutablePointer
}

That though results in the following error:

Cannot convert value of type 'UnsafeRawBufferPointer' to expected argument type 'UnsafePointer'

Perhaps I just haven't found the right question or the right documentation page yet, so I'd appreciate any pointers in the right direction!

arik
  • 28,170
  • 36
  • 100
  • 156

1 Answers1

1

The withXXXBytes methods get you raw pointers, but here you want a typed pointer. Use withUnsafeMutableBufferPointer instead and get the base address:

arrayOfUInt16.withUnsafeMutableBufferPointer { (bufferPointer) in
    let mutablePointerOfUInt16 = bufferPointer.baseAddress
    // do whatever you want with mutablePointerOfUInt16
    // just don't "store or return the pointer for later use." as the documentation says 
    // because the pointer is only valid within this block
}
Sweeper
  • 213,210
  • 22
  • 193
  • 313
  • This works, thank you! In my specific case, array is an immutable argument to the method this conversion happens in, so I used `withUnsafeBufferPointer` instead. – arik Apr 02 '21 at 16:38