withUnsafeBytes et interopérabilité C
Faites l’interface avec les API C qui attendent des octets bruts.
withUnsafeBytes et interopérabilité C est une leçon Swift Academy gratuite sur CoddyKit. Ceci est la leçon 4 sur 4. Tu peux lire la leçon complète ci-dessous gratuitement — puis la pratiquer en direct dans le navigateur avec un éditeur de code intégré et un tuteur IA 24/7. Elle fait partie du parcours d'apprentissage Swift Academy, et ta progression se synchronise sur le web et l'application CoddyKit. Le cours Swift Academy comprend 4 leçons au total.
Des valeurs typées aux octets raw
Vous devez parfois examiner une valeur non pas comme un Int ou une struct, mais comme une séquence d'octets raw — pour la hacher, l'écrire dans un fichier ou la transmettre à une API C. withUnsafeBytes vous fournit exactement cela : une vue temporaire du stockage d'une valeur sous forme de UInt8.
var value: UInt32 = 0x01020304
withUnsafeBytes(of: &value) { rawBuffer in
print(rawBuffer.count) // 4 bytes
}Le pointeur de tampon brut UnsafeRawBufferPointer
La fermeture reçoit un UnsafeRawBufferPointer — un buffer d'octets sans type d'élément. Vous l'indexez pour lire des valeurs UInt8 individuelles. Il est en lecture seule ; la forme modifiable est withUnsafeMutableBytes.
var value: UInt32 = 0x01020304
withUnsafeBytes(of: &value) { bytes in
for b in bytes { print(String(format: "%02x", b)) }
}
// Order depends on endiannessL'ordre des octets est important
L'ordre des octets que vous observez dépend de l'ordre des octets de la plateforme. Sur les machines little-endian (Apple silicon, Intel), l'octet de poids faible vient en premier. Lors de la sérialisation pour un protocole, effectuez une conversion explicite avec bigEndian ou littleEndian.
let host: UInt32 = 0x01020304
let networkOrder = host.bigEndian
var be = networkOrder
withUnsafeBytes(of: &be) { bytes in
// Always 01 02 03 04 regardless of platform
print(Array(bytes))
}Les octets d'une structure
withUnsafeBytes(of:) fonctionne avec n'importe quelle valeur, y compris les structures. La longueur du buffer est égale à MemoryLayout<T>.size et les octets de remplissage éventuels sont inclus, mais leur contenu n'est pas spécifié.
struct RGB { var r: UInt8; var g: UInt8; var b: UInt8 }
var color = RGB(r: 255, g: 128, b: 0)
withUnsafeBytes(of: &color) { bytes in
print(bytes[0], bytes[1], bytes[2]) // 255 128 0
}Charger une valeur à partir d'octets
Pour réinterpréter des octets raw comme une valeur typed, utilisez load(fromByteOffset:as:) sur un buffer raw. Le décalage doit respecter l'alignement du type, et les octets doivent effectivement représenter une valeur valide de ce type.
let raw: [UInt8] = [0x04, 0x03, 0x02, 0x01]
let n = raw.withUnsafeBytes { ptr in
ptr.load(fromByteOffset: 0, as: UInt32.self)
}
print(String(format: "0x%08x", n))loadUnaligned pour les données compactées
Les formats binaires regroupent souvent les champs sans remplissage d'alignement. Appeler load à un décalage non aligné constitue un comportement indéfini ; utilisez plutôt loadUnaligned(fromByteOffset:as:) pour lire en toute sécurité depuis n'importe quel décalage.
let packet: [UInt8] = [0xFF, 0x04, 0x03, 0x02, 0x01]
let field = packet.withUnsafeBytes { ptr in
ptr.loadUnaligned(fromByteOffset: 1, as: UInt32.self)
}
print(field)Relier Data de Swift à C
De nombreuses fonctions C acceptent un const void * accompagné d'une longueur. Data et les tableaux exposent withUnsafeBytes, ce qui vous permet de transmettre directement baseAddress et count, sans copie.
import Foundation
let data = Data([0x68, 0x69]) // "hi"
data.withUnsafeBytes { (raw: UnsafeRawBufferPointer) in
if let base = raw.baseAddress {
// c_consume(base, raw.count)
print("ptr", base, "len", raw.count)
}
}Recevoir un pointeur C
Lorsqu'un rappel C vous transmet un const void * et une longueur, encapsulez-les dans un UnsafeRawBufferPointer pour les parcourir en toute sécurité. Swift importe le pointeur C sous la forme UnsafeRawPointer?.
func handleC(_ ptr: UnsafeRawPointer, _ len: Int) {
let buffer = UnsafeRawBufferPointer(start: ptr, count: len)
let checksum = buffer.reduce(0) { $0 &+ Int($1) }
print("checksum:", checksum)
}bindMemory et réinterprétation
Pour traiter une région raw comme des éléments typés, bindMemory(to:capacity:) indique au compilateur comment l'interpréter. Une mauvaise utilisation — lier la même mémoire à deux types incompatibles — enfreint les règles strictes d'aliasing de Swift et produit un comportement indéfini.
let raw = UnsafeMutableRawPointer.allocate(
byteCount: 8, alignment: 8)
defer { raw.deallocate() }
let typed = raw.bindMemory(to: Int.self, capacity: 1)
typed.pointee = 1234
print(typed.pointee)assumingMemoryBound ou bindMemory
bindMemory modifie définitivement la manière dont la mémoire est interprétée ; assumingMemoryBound(to:) affirme qu'elle est déjà liée à ce type, sans rien modifier. N'utilisez cette dernière option que si vous êtes certain de la liaison existante, par exemple pour une mémoire dont vous savez qu'elle contient le type concerné.
func sumInts(_ raw: UnsafeRawPointer, _ count: Int) -> Int {
let p = raw.assumingMemoryBound(to: Int.self)
var total = 0
for i in 0..<count { total += p[i] }
return total
}Liste de vérification de la sécurité
L'interopérabilité avec les octets raw et C est l'endroit où se cachent la plupart des plantages. Souvenez-vous des points suivants :
- Ne laissez jamais le pointeur de la fermeture s'échapper.
- Respectez l'alignement ou utilisez les variantes
Unaligned. - Gérez explicitement l'ordre des octets lors de la sérialisation.
- Ne liez pas de nouveau la mémoire à des types incompatibles.
- Prévoyez le cas où
baseAddressvautnilpour les buffers vides.
// Convert any value to a hex string safely
import Foundation
func hex<T>(_ v: T) -> String {
var value = v
return withUnsafeBytes(of: &value) { bytes in
bytes.map { String(format: "%02x", $0) }.joined()
}
}Vérification rapide
Vérifiez votre compréhension de la lecture de données binaires compactées.
Récapitulatif
Vous avez appris à relier les valeurs Swift et C au moyen d'octets raw :
withUnsafeBytes(of:)présente n'importe quelle valeur sous forme deUInt8.load/loadUnalignedréinterprètent les octets comme des valeurs typées, en respectant l'alignement.Dataet les tableaux exposentwithUnsafeBytespour transmettre un pointeur et une longueur à C.bindMemoryetassumingMemoryBoundcontrôlent le typage de la mémoire raw.- L'ordre des octets, l'alignement et l'échappement des pointeurs sont les principaux dangers.
Questions Fréquemment Posées
La leçon « withUnsafeBytes et interopérabilité C » est-elle gratuite ?
Oui — le texte complet de « withUnsafeBytes et interopérabilité C » est gratuit à lire ici sur le web. Pour la pratiquer de manière interactive (un éditeur de code intégré et un tuteur IA 24/7) et déverrouiller le reste du cours Swift Academy, passe à CoddyKit PRO. Le cours Swift Academy comprend 4 leçons au total.
Qu'est-ce que j'apprendrai dans « withUnsafeBytes et interopérabilité C » ?
Faites l’interface avec les API C qui attendent des octets bruts. Tu pratiques Swift Academy avec du code pratique que tu exécutes directement dans le navigateur, et un tuteur IA 24/7 répond à tes questions au fur et à mesure que tu avances dans la leçon.
Dois-je avoir de l'expérience pour commencer Swift Academy ?
Aucune expérience préalable n'est requise. Swift Academy sur CoddyKit est structuré pour les débutants jusqu'aux apprenants avancés, donc tu peux commencer ici ou depuis le début et avancer à ton rythme. Ceci est la leçon 4 sur 4.
Combien de temps prend la leçon « withUnsafeBytes et interopérabilité C » ?
La plupart des leçons CoddyKit prennent environ 5–10 minutes. Chacune est courte et interactive, tu progresses régulièrement et tu repiques exactement où tu t'es arrêté sur le web et l'app.
Peux-tu écrire et exécuter du code dans cette leçon Swift Academy ?
Oui. Chaque leçon Swift Academy inclut un éditeur de code intégré, tu écris et exécutes du vrai code directement dans ton navigateur et tu reçois des retours IA instantanés — aucune configuration locale requise.
Toutes les leçons de ce cours
- MemoryLayout et alignement
- UnsafePointer et UnsafeMutablePointer
- Pointeurs de tampons non sûrs
- withUnsafeBytes et interopérabilité C