2

I have the following code in Objective-C:

- (double)readDouble
{
    double value = 0.0;

    if ([self read:(uint8_t *)&value maxLength:8] != 8)
    {
        NSLog(@"***** Couldn't read double");
    }

    return value;
}

It works. But I don't know how to convert it to Swift. Here is my code:

public func readDouble() -> Double {

    var value : Double = 0.0

    var num = self.read((uint8_t *)&value, maxLength:8) // got compiling error here!
    if num != 8 {

    }
}

The error message is:

Cannot invoke '&' with an argument list of type '($T4, maxLength: IntegerLiteralConvertible)'

Can anybody help? Thanks

The testing data I'm using (1.25):

14 AE 47 E1 7A 14 F4 3F

UPDATE:

A simple c solution, but how to do this in Swift?

double d = 0;
unsigned char buf[sizeof d] = {0};

memcpy(&d, buf, sizeof d);
Martijn Pieters
  • 1,048,767
  • 296
  • 4,058
  • 3,343
Bagusflyer
  • 12,675
  • 21
  • 96
  • 179

3 Answers3

3

This should work:

let num = withUnsafeMutablePointer(&value) {
    self.read(UnsafeMutablePointer($0), maxLength: sizeofValue(value))
}

Explanation: withUnsafeMutablePointer() calls the closure (block) with the only argument ($0 in shorthand notation) set to the address of value.

$0 has the type UnsafeMutablePointer<Double> and read() expects an UnsafeMutablePointer<UInt8> as the first argument, therefore another conversion is necessary. The return value of the closure is then assigned to num.

Martin R
  • 529,903
  • 94
  • 1,240
  • 1,382
  • Sorry. It doesn't work. I got **"Cannot invoke 'init' with an argument list of type '(UnsafeMutablePointer, maxLength: IntegerLiteralConvertible)'"** – Bagusflyer Sep 15 '14 at 10:43
  • OK, I'll try. By the way, I'm not the one why downvote your answer. I'll up vote for you anyway. – Bagusflyer Sep 15 '14 at 11:06
  • But it seems the result is not correct. Where is the result? In value, am I right? – Bagusflyer Sep 15 '14 at 11:14
  • The result is: num = 8,value = 3.31609222784626e-296 – Bagusflyer Sep 15 '14 at 11:19
  • @bagusflyer: According to http://www.binaryconvert.com/result_double.html?decimal=049046050053, the binary "Double" representation of 1.25 is 0x3FF4000000000000. Also note that iOS uses little-endian representation. I have tested the code now with a data file containing `00 00 00 00 00 00 F4 3F`, and the result was `value = 1.25`. – Martin R Sep 15 '14 at 11:23
  • @bagusflyer: I have now tested the code with your data `14 AE 47 E1 7A 14 F4 3F` and the result was `value = 1.255` – Martin R Sep 15 '14 at 11:32
  • Let us [continue this discussion in chat](http://chat.stackoverflow.com/rooms/61265/discussion-between-bagusflyer-and-martin-r). – Bagusflyer Sep 15 '14 at 11:37
1

The method above does not work for me, using Swift 2 but I discovered a much more simpler method to do this conversion and vice versa:

func binarytotype <T> (value: [UInt8], _: T.Type) -> T
{
    return value.withUnsafeBufferPointer
    {
        return UnsafePointer<T>($0.baseAddress).memory
    }
}

func typetobinary <T> (var value: T) -> [UInt8]
{
    return withUnsafePointer(&value)
    {
        Array(UnsafeBufferPointer(start: UnsafePointer<UInt8>($0), count: sizeof(T)))
    }
}

let a: Double = 0.25
let b: [UInt8] = typetobinary(a) // -> [0, 0, 0, 0, 0, 0, 208, 63]
let c = binarytotype(b, Double.self) // -> 0.25

I have tested it with Xcode 7.2 in the playground.

j.s.com
  • 1,422
  • 14
  • 24
0

Here is the updated version for Swift 3 beta 6 which is different, thanx to Martin.

func binarytotype <T> (_ value: [UInt8], _ : T.Type) -> T
{
    return value.withUnsafeBufferPointer
    {
        UnsafeRawPointer($0.baseAddress!).load(as: T.self)
    }
}

func typetobinary <T> (_ value: T) -> [UInt8]
{
    var v = value
    let size = MemoryLayout<T>.size
    return withUnsafePointer(to: &v)
    {
        $0.withMemoryRebound(to: UInt8.self, capacity: size)
        {
            Array(UnsafeBufferPointer(start: $0, count: size))
        }
    }    
}

let dd: Double = 1.23456             // -> 1.23456
let d = typetobinary(dd)             // -> [56, 50, 143, 252, 193, 192, 243, 63]
let i = binarytotype(d, Double.self) // -> 1.23456
j.s.com
  • 1,422
  • 14
  • 24