首页 > 解决方案 > Swift 到 Kotlin 之谜

问题描述

我正在将一些 iOS 代码(Swift)转换为用于控制蓝牙设备(BLE)的 Android(Kotlin)。

我相信 Swift 和 Kotlin 以及 Unsigned Ints 等之间存在一些差异,但我似乎无法获得相同的输出。

iOS 代码:输出 13365

print ("IMPORTANT \(fourthData as NSData)") // Value is 0x3534
var fourth = Int32()
_ = Swift.withUnsafeMutableBytes(of: &fourth, { fourthData.copyBytes(to: $0) } )
print ("IMPORTANT \(fourth)") // 13365

Android 代码:输出为 13620

@ExperimentalUnsignedTypes // just to make it clear that the experimental unsigned types are used
    fun ByteArray.toHexString() = asUByteArray().joinToString("") { it.toString(16).padStart(2, '0') }

Log.i("Decode", fourthData.toHexString()) // 3534 
Log.i("Decode", "${fourthData.toHexString().toUInt(16)}") //13620

我尝试过 Int、UInt BigInteger 和 Long。我错过了什么

标签: swiftkotlin

解决方案


正如评论者已经指出的那样,values1362013365are0x35340x3435分别。换句话说,值因字节顺序而异。

十进制的 32 位数字13620等于0x00003534十六进制,因此它将由四个字节表示00-00-35-34

但是,计算机通常不会按该顺序表示值。两种常用的表示是Big Endian和Little Endian。Big Endian 将按自然顺序表示字节,00-00-35-34但 Little Endian 会将字节交换为00-00-34-35.

Java (Kotlin) 总是对所有内容使用 Big Endian 表示。另一方面,如果你只是Int在 Swift 中得到一个内存布局,你就会得到机器表示。机器表示通常是 Little Endian,但在架构之间可能会有所不同。当直接将数值重新解释为字节时,您应该始终小心,反之亦然。

在这种特定情况下,如果您确定Data包含 Big Endian 整数,则可以使用Int32(bigEndian: fourth)将值从 Big Endian 交换为机器表示。


推荐阅读