cswiftunsafemutablepointeruint16

Swift convert [UIn16] to UnsafeMutablePointer<UInt16>


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!


Solution

  • 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
    }