In Swift 3, how do I get UnsafeRawPointer from Data?

Check the latest reference.

We cannot find a method or property which retrieves UnsafeRawPointer from a Data.

So, for alternative: func withUnsafeBytes((UnsafePointer) -> ResultType)

You can write something like this:

let data: Data = <initialize it as you like>

data.withUnsafeBytes {(uint8Ptr: UnsafePointer<UInt8>) in
    let rawPtr = UnsafeRawPointer(uint8Ptr)
    //`rawPtr` (and `uint8Ptr`) is guaranteed to be valid in this closure
    //...
    //You have no need manage `rawPtr`.
}

(Oh, this is the same as the first half of Martin R's answer.)


But if you want to keep your UnsafeRawPointer valid for a longer period than in a closure, you need to make a copy of the content of the Data:

For example:

let uint8Ptr = UnsafeMutablePointer<UInt8>.allocate(capacity: data.count)
uint8Ptr.initialize(from: data) //<-copying the data
//You need to keep `uint8Ptr` and `data.count` for future management
let uint8PtrCount = data.count
//You can convert it to `UnsafeRawPointer`
let rawPtr = UnsafeRawPointer(uint8Ptr)
//Use `rawPtr` while `uint8Ptr` is valid
//...
//Deinitialize and deallocate the region
uint8Ptr.deinitialize(count: uint8PtrCount)
uint8Ptr.deallocate(capacity: uint8PtrCount)

(You can get UnsafeMutableRawPointer as a return value of deinitialize(count:), but the region is in an uninitialized state, so you should not access the region.)


In Swift 5:

'withUnsafeBytes' is deprecated: use `withUnsafeBytes<R>(_: (UnsafeRawBufferPointer) throws -> R) rethrows -> R` instead

A possible solution is:

buffer.withUnsafeBytes{ (bufferRawBufferPointer) -> Void in

    let bufferPointer: UnsafePointer<UInt8> = bufferRawBufferPointer.baseAddress!.assumingMemoryBound(to: UInt8.self)
    let rawPtr = UnsafeRawPointer(bufferPointer)
    //USE THE rawPtr

}

withUnsafeBytes() gives you a (typed) pointer to the bytes, this can be converted to a raw pointer:

let data = <Data from somewhere>
data.withUnsafeBytes { (u8Ptr: UnsafePointer<UInt8>) in
    let rawPtr = UnsafeRawPointer(u8Ptr)
    // ... use `rawPtr` ...
}

The pointer is only valid during the lifetime of the call to the closure.

Alternatively, you can bridge to NSData and access the raw bytes:

let nsData = data as NSData
let rawPtr = nsData.bytes

Now the pointer is valid in the same scope where nsData is valid.

As of Swift 5 it is

let data = <Data from somewhere>
data.withUnsafeBytes { rawBufferPointer in
    let rawPtr = rawBufferPointer.baseAddress!
    // ... use `rawPtr` ...
}

because the closure argument is now a UnsafeRawBufferPointer.

Tags:

Swift

Swift3