2014-06-24 13 views
17

Sto provando a impostare l'endianness intero usando htonl() in Swift ma il compilatore non sta trovando il metodo htonl().Come si imposta il carattere intero con htonl in Swift?

ho usato questo come il mio riferimento: Append NSInteger to NSMutableData

Ecco il mio codice:

import Foundation 
import CFNetwork 
import CoreFoundation 

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

Ho appena stato in esecuzione questo in un parco giochi. L'errore è:

Use of unresolved identifier 'htonl' 

risposta

7

Aggiornamento: la risposta di Martin R è la risposta corretta per le attuali versioni di Swift: https://stackoverflow.com/a/24653879/195691

-

si dovrebbe utilizzare il metodo CFSwapInt32HostToBig() CoreFoundation, come htonl è probabilmente implementato come macro C che non funzionerà in modo rapido.

Tuttavia, sembra che al momento non funzioni nel parco giochi Swift. Ricevo l'errore Playground execution failed: error: error: Couldn't lookup symbols: __OSSwapInt32 nonostante il fatto che la documentazione di CoreFoundation ora includa le firme dei metodi in Swift per i suoi metodi di scambio dei byte.

È interessante notare, sembra che almeno una parte del <arpa/inet.h> è stato portato alla rapida, come metodi come inet_ntoa() e inet_addr() sono disponibili per Swift, ma la famiglia non è htonl.

+0

Impressionante, grazie! Sembra che funzionerà. Ho finito per implementare htonl() in un header bridging/native-c ma passerò a questo. – Michael

+0

Giusto. htonl/htons etc è una macro e quindi non viene importata in Swift (le funzioni di varargs C come ioctl/fcntl sono un'altra cosa comune mancante). Se conosci l'endianess è facile reimplementare: func ntohs (valore: CUnsignedShort) -> CUnsignedShort { // hm, htons non è una funzione in OSX e la macro non è mappata return (valore << 8) + (valore >> 8); let htons = ntohs // stessa cosa, scambia byte :-) – hnh

+0

In realtà 'CFSwapInt32HostToBig' e gli amici sono ora disponibili in Swift che viene fornito con Xcode 6.1.1 :) –

29

Al Xcode 6, Beta 3, tutti i tipi interi hanno un metodo bigEndian che restituisce la rappresentazione big-endian del numero intero e cambia l'ordine byte se necessario.Esempio:

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

Aggiornamento per Swift 3:

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

Oppure, utilizzando il nuovo tipo Data valore:

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

Se stai cercando la direzione opposta (network to host), hai 'UInt32 (bigEndian: number)', e 'inits' simili per altri tipi di interi. –

3

Invece di utilizzare CFSwapInt32HostToBig() come Alex Pretzlav si consiglia dovrebbe usare

CFSwapInt32() 

invece di

ntonl() and ntohl() 

e

CFSwapInt16() 

invece di

ntons() and ntohs() 

Il codice dovrebbe essere simile

import Foundation 
import CFNetwork 
import CoreFoundation 

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

Inoltre c'è

CFSwapInt64() 

per lo scambio di numeri interi 8-byted.

Modifica 1

Ovviamente si deve utilizzare queste funzioni solo su processori con piccoli numeri interi endian causa funzioni ho fornito eseguire byte di swap in ogni caso.

Problemi correlati