Как установить целочисленную endianness с помощью htonl в Swift?

Я пытаюсь установить целочисленную endianness с помощью htonl() в Swift, но компилятор не находит метод htonl().

Я использовал это как мою ссылку: Добавить NSInteger в NSMutableData

Здесь мой код:

import Foundation
import CFNetwork
import CoreFoundation

var data = NSMutableData()
var number : UInt32 = 12
var convertedNumber : UInt32 = htonl(number)
data.appendBytes(&convertedNumber, length: 4)

Я только что запустил это на детской площадке. Ошибка:

Use of unresolved identifier 'htonl'

Ответы

Ответ 1

Обновить: ответ Martin R - правильный ответ для текущих версий Swift: fooobar.com/questions/331555/...

-

Вы должны использовать метод CFSwapInt32HostToBig() CoreFoundation, поскольку htonl, скорее всего, реализован как макрос C, который не будет работать в swift.

Однако, похоже, что это не работает в детской площадке Swift. Я получаю сообщение об ошибке Playground execution failed: error: error: Couldn't lookup symbols: __OSSwapInt32, несмотря на то, что документация CoreFoundation теперь включает в себя сигнатуры методов в Swift для своих методов замены байтов.

Интересно, что по крайней мере часть <arpa/inet.h> была перенесена на скорость, так как для Swift доступны такие методы, как inet_ntoa() и inet_addr(), но в семействе htonl нет.

Ответ 2

Начиная с Xcode 6, Beta 3, все целые типы имеют метод bigEndian, который возвращает большое представление целого числа и изменяет если необходимо, порядок байтов. Пример:

var data = NSMutableData()
var number : UInt32 = 0x12345678
var convertedNumber = number.bigEndian
data.appendBytes(&convertedNumber, length: 4)
print(data)
// Output: <12345678>

Обновление для Swift 3:

let data = NSMutableData()
let number: UInt32 = 0x12345678
var convertedNumber = number.bigEndian
data.append(&convertedNumber, length: 4)

Или, используя новый тип значения Data:

var data = Data()
let number: UInt32 = 0x12345678
var convertedNumber = number.bigEndian
withUnsafePointer(to: &convertedNumber) {
    data.append(UnsafeRawPointer($0).assumingMemoryBound(to: UInt8.self), count: 4)
}

Ответ 3

Вместо использования CFSwapInt32HostToBig(), поскольку Алекс Претцлав посоветовал вам использовать

CFSwapInt32()

вместо

ntonl() and ntohl()

и

CFSwapInt16()

вместо

ntons() and ntohs()

Ваш код должен выглядеть как

import Foundation
import CFNetwork
import CoreFoundation

var data = NSMutableData()
var number : UInt32 = 12
var convertedNumber : UInt32 = CFSwapInt32(number)
data.appendBytes(&convertedNumber, length: 4)

Также есть

CFSwapInt64()

для 8-байтового целочисленного обмена.

Изменить 1

Конечно, вы должны использовать эти функции только для процессоров с небольшим числом целых чисел, вызывающих функции, которые я предоставил, чтобы выполнить байтов в любом случае.