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);
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
.
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.
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