FFI
A redefinição:
@cimportlê o header do C direto, e todo o estrangeiro vive sobc.. O ponto grita “isto é C” em cada contato.
O conceito
Seção intitulada “O conceito”Falar com C é obrigatório para uma linguagem de sistemas: o ecossistema de meio século está em C. A forma tradicional é escrever bindings à mão (redeclarar cada protótipo, cada struct, manter isso em sincronia) ou gerar bindings com uma ferramenta externa. De um jeito ou de outro, você reconstrói o que o C já expõe.
Como Makoto redefine
Seção intitulada “Como Makoto redefine”@cimport("header.h") roda em comptime, invoca um compilador C embutido, traduz o header inteiro e
devolve um módulo sob o namespace-raiz c. Você não redeclara nada: @cimport("stdio.h") te dá
c.stdio.printf direto. Os tipos fundamentais (dependentes de compilador/plataforma) vêm de um runtime
importado: c.gcc.size_t é o size_t como o GCC o define.
Tudo do C fica sob c., e isso é proposital: o ponto grita “aqui há contrato C, não Makoto” em
todo ponto de contato, e o seu namespace fica limpo (quem não faz FFI nunca vê nada de C). Chamar C é
unsafe (cada chamada é uma caixa-preta que pode violar qualquer invariante), abatido com
assert/assume ou agrupado num bloco; e o retorno valida na borda (ponteiro que pode ser NULL
vira Optional, bytes que viram string passam por Result).
Na fronteira, a memória continua colorless: @mm(c) (o gerenciador delega para o free do C),
@promote(gc) (repatria para o GC), @pin/@unpin (fixa um objeto GC enquanto o C o segura). E o
irmão mais baixo: inline assembly via @asm.
O raciocínio
Seção intitulada “O raciocínio”A aposta é “o ecossistema C de graça, se você aceitar a marca de segurança”. Se o C é inerentemente
unsafe, reescrever bindings à mão não compra segurança nenhuma; só adiciona burocracia e uma cópia que
desincroniza. Melhor ler o header direto (a fonte da verdade já existe) e gastar o esforço onde ele
importa: na fronteira, marcando o perigo (unsafe, validação na borda) e o crossing de memória
(@mm(c)/@promote/@pin).
O namespace c. é o não-envenenamento aplicado à FFI (cap. 01): o estrangeiro não polui o global,
e a marca é o próprio caminho do nome. É o mesmo motivo de unsafe ser uma marca e não um modo
silencioso: perigo deve ser visível, e c.malloc no meio do seu código é visível.
Por que não as alternativas
Seção intitulada “Por que não as alternativas”- Bindings escritos à mão. Reconstroem o que o C já expõe, desincronizam quando o header muda, e
não compram segurança (C continua unsafe).
@cimportlê a fonte da verdade. - FFI sem namespace dedicado (
extern "C"no escopo, à la Zig@import("c")misturado). Nomes colidem (opené seu ou do C?) e a fronteira fica invisível. Oc.desambigua e marca. - Conversão automática
intCi32Makoto. Esconderia o custo: em alguns alvosinté 32 bits, em outros 64, e o bug fica invisível. Os tipos do C vêm explícitos (c.gcc.size_t); o crossing é escrito. - Coloring de async/memória atravessando a fronteira automaticamente. A memória do C chega
@mm(c)e você decide o que fazer (@promote,@pin), explícito, porque cruzar mundos é uma decisão, não uma coerção.
A dor concreta
Seção intitulada “A dor concreta”O projeto que mantém um arquivo de bindings de 2000 linhas em sincronia manual com um header que muda a
cada release. O Zig em que você passa um i32 para um parâmetro int do C e funciona em x86 mas quebra
em outro alvo, sem nenhuma pista no código. O NULL que volta de uma função C e vira segfault três
chamadas adiante porque ninguém o tratou. Cada uma é a fronteira C mal-marcada cobrando o preço.
O modelo mental
Seção intitulada “O modelo mental”Aponta para o
.h, e o C funciona. Todo o estrangeiro vive sobc.(que grita “isto é C”); o perigo éunsafee a memória cruza os mundos explicitamente.
A fricção aceita
Seção intitulada “A fricção aceita”@cimport exige um compilador C embutido na toolchain (peso real, mas paga-se uma vez). Cada chamada a
C carrega a obrigação de unsafe + validação na borda, mais cerimônia que um simples call, de
propósito, porque o perigo é real. E o c. em cada nome é verboso quando você usa C intensamente, mas
é a marca que mantém a fronteira honesta.
Próximo: 11 · Ecossistema e tiers