10

I have a little Problem with my Code after updating to Swift 3. I had this Code before the conversion:

extension NSData {
  func castToCPointer<T>() -> T {
    let mem = UnsafeMutablePointer<T>.alloc(sizeof(T.Type))
    self.getBytes(mem, length: sizeof(T.Type))
    return mem.move()
  }
}

And I converted it to this Code and in the 3rd line I get an Error

... Cannot convert value of type 'UnsafeMutablePointer' to expected argument type 'UnsafeMutablePointer'

extension Data {
  func castToCPointer<T>() -> T{
    let mem = UnsafeMutablePointer<T>.allocate(capacity: MemoryLayout<T.Type>.size)
    self.copyBytes(to: mem, count: MemoryLayout<T.Type>.size)
    //self.copyBytes(to: mem, count: MemoryLayout<T.Type>.size)
    return mem.move()
  }
}

Does anyone know how to get rid of this?

Martin R
  • 529,903
  • 94
  • 1,240
  • 1,382
Luke Pistrol
  • 1,199
  • 3
  • 12
  • 26

2 Answers2

8

copyBytes expects a UnsafeMutableBufferPointer as argument:

extension Data {
    func castToCPointer<T>() -> T {
        let mem = UnsafeMutablePointer<T>.allocate(capacity: 1)
        _ = self.copyBytes(to: UnsafeMutableBufferPointer(start: mem, count: 1))
        return mem.move()
    }
}

(allocate() takes the number of "items" as argument, not the number of bytes.)

But note that your method leaks memory, the allocated memory is deinitialized (with move()) but also has to be deallocated:

extension Data {
    func castToCPointer<T>() -> T {
        let mem = UnsafeMutablePointer<T>.allocate(capacity: 1)
        _ = self.copyBytes(to: UnsafeMutableBufferPointer(start: mem, count: 1))
        let val =  mem.move()
        mem.deallocate()
        return val
    }
}
Martin R
  • 529,903
  • 94
  • 1,240
  • 1,382
  • Xcode 14 compiler produces this warning which I don't know how to apply: 'withUnsafeBytes' is deprecated: use `withUnsafeBytes(_: (UnsafeRawBufferPointer) throws -> R) rethrows -> R` instead – Nate Lockwood May 16 '23 at 21:44
  • @NateLockwood: I have updated the first method for the current Swift and removed the second method. While it would have been possible to update the second method for Swift 5 as well that one always had the disadvantage to work only with properly aligned memory (which is impossible to guarantee). – Martin R May 16 '23 at 23:17
-1

You can also use below syntax in extension

extension Data {
    func castToCPointer<T>() -> T {
        var bytes = self.bytes
        var val = withUnsafePointer(to: &bytes) { (temp) in
            return unsafeBitCast(temp, to: T.self)
        }
        return val
    }
}

var data:NSData/NSMutableData
var bytes = data.bytes
var val = withUnsafePointer(to: &bytes) { (temp) in
   return unsafeBitCast(temp, to: T.self)
}
Ankit Thakur
  • 4,739
  • 1
  • 19
  • 35