withUnsafeBytes e Interoperabilidade com C
Faça a ponte com APIs de C que esperam bytes brutos.
withUnsafeBytes e Interoperabilidade com C é uma aula grátis de Swift Academy no CoddyKit. Esta é a aula 4 de 4. Você pode ler a aula completa abaixo gratuitamente — depois pratica ao vivo no navegador com um editor de código integrado e um tutor de IA 24/7. Faz parte do caminho de aprendizado de Swift Academy, e seu progresso é sincronizado entre a web e o app CoddyKit. O curso de Swift Academy inclui 4 aulas no total.
De valores tipados a bytes brutos
Às vezes, você precisa ver um valor não como um Int ou uma struct, mas como uma sequência de bytes brutos — para calcular seu hash, gravá-lo em um arquivo ou passá-lo a uma API de C. withUnsafeBytes oferece exatamente isso: uma visão temporária do armazenamento de um valor como UInt8.
var value: UInt32 = 0x01020304
withUnsafeBytes(of: &value) { rawBuffer in
print(rawBuffer.count) // 4 bytes
}O UnsafeRawBufferPointer
O bloco recebe um UnsafeRawBufferPointer — um buffer de bytes sem tipo de elemento. Você o indexa para ler valores individuais de UInt8. Ele é somente de leitura; a forma mutável é withUnsafeMutableBytes.
var value: UInt32 = 0x01020304
withUnsafeBytes(of: &value) { bytes in
for b in bytes { print(String(format: "%02x", b)) }
}
// Order depends on endiannessA ordem dos bytes é importante
A ordem dos bytes que você observa depende da ordem dos bytes da plataforma. Em máquinas little-endian (Apple silicon, Intel), o byte menos significativo vem primeiro. Ao serializar para um protocolo, faça a conversão explicitamente com 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))
}Bytes de uma struct
withUnsafeBytes(of:) funciona com qualquer valor, inclusive structs. O comprimento do buffer é igual a MemoryLayout<T>.size, e quaisquer bytes de preenchimento são incluídos, mas seu conteúdo não é especificado.
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
}Carregando um valor a partir de bytes
Para reinterpretar bytes brutos como um valor tipado, use load(fromByteOffset:as:) em um buffer bruto. O deslocamento deve respeitar o alinhamento do tipo, e os bytes precisam representar de fato um valor válido desse tipo.
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 para dados compactados
Os formatos binários frequentemente compactam campos sem preenchimento de alinhamento. Chamar load em um deslocamento não alinhado resulta em comportamento indefinido; em vez disso, use loadUnaligned(fromByteOffset:as:) para ler com segurança a partir de qualquer deslocamento.
let packet: [UInt8] = [0xFF, 0x04, 0x03, 0x02, 0x01]
let field = packet.withUnsafeBytes { ptr in
ptr.loadUnaligned(fromByteOffset: 1, as: UInt32.self)
}
print(field)Fazendo a ponte entre Data do Swift e C
Muitas funções de C aceitam um const void * junto com um comprimento. Data e os arrays expõem withUnsafeBytes, permitindo passar baseAddress e count diretamente, sem copiar.
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)
}
}Recebendo um ponteiro de C
Quando um retorno de chamada de C fornece um const void * e um comprimento, envolva-os em um UnsafeRawBufferPointer para iterar com segurança. O Swift importará o ponteiro de C como 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 e reinterpretação
Para tratar uma região bruta como elementos tipados, bindMemory(to:capacity:) informa ao compilador como interpretá-la. Usar isso incorretamente — vinculando a mesma memória a dois tipos incompatíveis — viola as regras estritas de compatibilidade de tipos do Swift e resulta em comportamento indefinido.
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 e bindMemory
bindMemory altera permanentemente a forma como a memória é interpretada; assumingMemoryBound(to:) afirma que ela já está vinculada a esse tipo, sem alterar nada. Use o segundo somente quando tiver certeza da vinculação existente, como no caso de uma memória que você sabe que contém o tipo fornecido.
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
}Lista de verificação de segurança
A interoperabilidade entre bytes brutos e C é onde a maioria das falhas se esconde. Lembre-se:
- Nunca permita que o ponteiro do bloco escape.
- Respeite o alinhamento ou use as variantes
Unaligned. - Trate explicitamente a ordem dos bytes ao serializar.
- Não vincule novamente a memória a tipos conflitantes.
- Proteja-se contra um
baseAddressnilem buffers vazios.
// 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()
}
}Verificação rápida
Teste sua compreensão da leitura de dados binários compactados.
Recapitulação
Você aprendeu a fazer a ponte entre valores do Swift e C por meio de bytes brutos:
withUnsafeBytes(of:)apresenta qualquer valor comoUInt8.load/loadUnalignedreinterpretam bytes como valores tipados, respeitando o alinhamento.Datae os arrays expõemwithUnsafeBytespara passar ponteiro + comprimento ao C.bindMemoryeassumingMemoryBoundcontrolam como a memória bruta é tipada.- A ordem dos bytes, o alinhamento e o escape do ponteiro são os principais riscos.
Perguntas Frequentes
A aula “withUnsafeBytes e Interoperabilidade com C” é grátis?
Sim — o texto completo de “withUnsafeBytes e Interoperabilidade com C” é grátis para ler aqui na web. Para praticá-la interativamente (um editor de código integrado e um tutor de IA 24/7) e desbloquear o restante do curso de Swift Academy, atualize para CoddyKit PRO. O curso de Swift Academy inclui 4 aulas no total.
O que vou aprender em “withUnsafeBytes e Interoperabilidade com C”?
Faça a ponte com APIs de C que esperam bytes brutos. Você pratica Swift Academy com código prático que executa diretamente no navegador, e um tutor de IA 24/7 responde suas dúvidas enquanto trabalha na aula.
Preciso ter experiência prévia para começar Swift Academy?
Nenhuma experiência prévia é necessária. Swift Academy no CoddyKit é estruturado para alunos iniciantes até avançados, então você pode começar aqui ou desde o início e aprender no seu ritmo. Esta é a aula 4 de 4.
Quanto tempo leva a aula “withUnsafeBytes e Interoperabilidade com C”?
A maioria das aulas CoddyKit leva cerca de 5–10 minutos. Cada uma é compacta e interativa, então você faz progresso constante e retoma exatamente de onde parou entre web e app.
Posso escrever e executar código nesta aula de Swift Academy?
Sim. Cada aula de Swift Academy inclui um editor de código integrado, então você escreve e executa código real direto no navegador e recebe feedback de IA instantaneamente — nenhuma configuração local necessária.
Todas as aulas deste curso
- MemoryLayout e Alinhamento
- UnsafePointer e UnsafeMutablePointer
- Ponteiros de Buffer Inseguros
- withUnsafeBytes e Interoperabilidade com C