9
votes

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?

2

2 Answers

8
votes

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(capacity: 1)
        return val
    }
}

A simpler solution would be (from round trip Swift number types to/from Data):

extension Data {
    func castToCPointer<T>() -> T {
        return self.withUnsafeBytes { $0.pointee }
    }
}
0
votes

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