---
title: "Cheatsheet: Interop com C em Zig"
url: "https://ziglang.com.br/cheatsheets/cheatsheet-interop-com-c-em-zig/"
markdown_url: "https://ziglang.com.br/cheatsheets/cheatsheet-interop-com-c-em-zig.MD"
description: "Referência rápida para interoperabilidade C/Zig: importar headers C, chamar funções C, linkar bibliotecas, tradução de tipos e exportar funções Zig para C. Guia completo em português."
date: "2026-02-21"
author: "Zig Brasil"
---

# Cheatsheet: Interop com C em Zig

Referência rápida para interoperabilidade C/Zig: importar headers C, chamar funções C, linkar bibliotecas, tradução de tipos e exportar funções Zig para C. Guia completo em português.


# Cheatsheet: Interop com C em Zig

Uma das grandes forças de Zig é a integração **nativa e sem fricção** com código C. O compilador Zig inclui um compilador C (baseado em Clang), pode importar headers C diretamente, linkar com bibliotecas C e até compilar código C como parte do projeto — tudo sem ferramentas externas.

## Importando Headers C

### @cImport — Importar headers C

```zig
const std = @import("std");
const c = @cImport({
    @cInclude("stdio.h");
    @cInclude("stdlib.h");
    @cInclude("string.h");
});

pub fn main() void {
    // Chamar printf do C
    _ = c.printf("Olá do C! %d\n", @as(c_int, 42));

    // malloc/free do C
    const ptr = c.malloc(100);
    if (ptr) |p| {
        defer c.free(p);
        // usar o ponteiro...
    }
}
```

### Importar biblioteca de terceiros

```zig
const c = @cImport({
    @cDefine("_GNU_SOURCE", {});           // #define
    @cDefine("SDL_MAIN_HANDLED", {});
    @cInclude("SDL2/SDL.h");
});

pub fn main() !void {
    if (c.SDL_Init(c.SDL_INIT_VIDEO) != 0) {
        std.debug.print("Erro SDL: {s}\n", .{c.SDL_GetError()});
        return error.SDLInitFailed;
    }
    defer c.SDL_Quit();

    // Criar janela, etc.
}
```

## Tradução de Tipos C → Zig

### Tabela de equivalência

| Tipo C | Tipo Zig | Notas |
|--------|----------|-------|
| `char` | `u8` | Em Zig, sempre unsigned |
| `signed char` | `i8` | |
| `unsigned char` | `u8` | |
| `short` | `c_short` | Geralmente i16 |
| `int` | `c_int` | Geralmente i32 |
| `long` | `c_long` | i32 ou i64 conforme plataforma |
| `long long` | `c_longlong` | Geralmente i64 |
| `unsigned int` | `c_uint` | |
| `size_t` | `usize` | |
| `float` | `f32` | |
| `double` | `f64` | |
| `void*` | `?*anyopaque` | Ponteiro opaco nullable |
| `const char*` | `[*:0]const u8` | String C terminada em null |
| `int*` | `*c_int` ou `[*]c_int` | Depende do uso |
| `NULL` | `null` | |
| `bool` (_Bool) | `bool` | |
| `struct X` | traduzido automaticamente | |
| `enum X` | traduzido automaticamente | |

### Conversões de ponteiros

```zig
const c = @cImport(@cInclude("string.h"));

pub fn main() void {
    // String Zig para C
    const zig_str: [:0]const u8 = "Olá";
    const c_str: [*:0]const u8 = zig_str.ptr;
    const len = c.strlen(c_str);
    std.debug.print("Tamanho: {d}\n", .{len});

    // Ponteiro C para slice Zig
    var buffer: [100]u8 = undefined;
    const c_ptr: [*]u8 = &buffer;
    const zig_slice: []u8 = c_ptr[0..50]; // criar slice com tamanho conhecido
    _ = zig_slice;

    // void* para tipo específico
    const void_ptr: ?*anyopaque = c.malloc(100);
    if (void_ptr) |p| {
        const typed_ptr: [*]u8 = @ptrCast(@alignCast(p));
        typed_ptr[0] = 42;
        c.free(p);
    }
}
```

## Chamar Funções C a Partir de Zig

### Exemplo com libc

```zig
const std = @import("std");
const c = @cImport({
    @cInclude("math.h");
    @cInclude("time.h");
});

pub fn main() void {
    // Funções matemáticas
    const raiz = c.sqrt(144.0);
    std.debug.print("Raiz de 144: {d}\n", .{raiz}); // 12.0

    const seno = c.sin(std.math.pi / 2.0);
    std.debug.print("sen(π/2): {d}\n", .{seno}); // 1.0

    // Tempo
    var agora: c.time_t = undefined;
    _ = c.time(&agora);
    const tm = c.localtime(&agora);
    if (tm) |t| {
        std.debug.print("Hora: {d}:{d:0>2}:{d:0>2}\n", .{
            t.*.tm_hour, t.*.tm_min, t.*.tm_sec,
        });
    }
}
```

### Callbacks — Passar função Zig para C

```zig
const c = @cImport(@cInclude("stdlib.h"));

fn comparar(a: ?*const anyopaque, b: ?*const anyopaque) callconv(.C) c_int {
    const val_a: *const i32 = @ptrCast(@alignCast(a));
    const val_b: *const i32 = @ptrCast(@alignCast(b));
    if (val_a.* < val_b.*) return -1;
    if (val_a.* > val_b.*) return 1;
    return 0;
}

pub fn main() void {
    var nums = [_]i32{ 5, 2, 8, 1, 9, 3 };

    // Usar qsort do C com callback Zig
    c.qsort(
        @ptrCast(&nums),
        nums.len,
        @sizeOf(i32),
        comparar,
    );

    // nums agora está ordenado: [1, 2, 3, 5, 8, 9]
    for (nums) |n| {
        std.debug.print("{d} ", .{n});
    }
}
```

## Exportar Funções Zig para C

### Criar biblioteca usável por C

```zig
// lib.zig — exportar funções para C
const std = @import("std");

export fn zig_somar(a: c_int, b: c_int) c_int {
    return a + b;
}

export fn zig_processar(dados: [*]u8, tamanho: usize) c_int {
    const slice = dados[0..tamanho];
    // processar dados...
    _ = slice;
    return 0; // sucesso
}

// Gerar header C automaticamente com:
// zig build-lib lib.zig -dynamic -femit-h
```

**Header gerado (lib.h):**
```c
int zig_somar(int a, int b);
int zig_processar(unsigned char* dados, size_t tamanho);
```

## Configuração no build.zig

### Linkar com bibliotecas C

```zig
pub fn build(b: *std.Build) void {
    const target = b.standardTargetOptions(.{});
    const optimize = b.standardOptimizeOption(.{});

    const exe = b.addExecutable(.{
        .name = "meu-app",
        .root_source_file = b.path("src/main.zig"),
        .target = target,
        .optimize = optimize,
    });

    // Linkar com libc
    exe.linkLibC();

    // Linkar com bibliotecas do sistema
    exe.linkSystemLibrary("SDL2");
    exe.linkSystemLibrary("openssl");
    exe.linkSystemLibrary("z"); // zlib

    // Caminhos de include
    exe.addIncludePath(b.path("include"));
    exe.addIncludePath(.{ .cwd_relative = "/usr/local/include" });

    // Caminhos de biblioteca
    exe.addLibraryPath(.{ .cwd_relative = "/usr/local/lib" });

    // Compilar arquivos C como parte do projeto
    exe.addCSourceFiles(.{
        .files = &.{
            "src/wrapper.c",
            "vendor/lib/util.c",
        },
        .flags = &.{
            "-Wall",
            "-O2",
            "-std=c11",
        },
    });

    b.installArtifact(exe);
}
```

## Structs C em Zig

```zig
// Struct compatível com layout C
const Ponto = extern struct {
    x: f64,
    y: f64,
    z: f64,
};

// Packed struct (sem padding)
const Header = packed struct {
    versao: u4,
    tipo: u4,
    tamanho: u16,
    flags: u8,
};

// Usar struct C importada
const c = @cImport(@cInclude("minha_lib.h"));

pub fn main() void {
    var ponto = c.criar_ponto(1.0, 2.0, 3.0);
    c.mover_ponto(&ponto, 10.0, 0.0, 0.0);
}
```

## Calling Conventions

```zig
// Padrão Zig (não compatível com C)
fn funcaoZig() void {}

// Convenção C — necessário para interop
fn funcaoC() callconv(.C) void {}

// Exportar para C
export fn exportada() c_int {
    return 0;
}

// Ponteiro de função com convenção C
const FnCallback = *const fn (c_int, c_int) callconv(.C) c_int;
```

## Erros Comuns

```zig
// ERRO: Esquecer de linkar libc
// exe.linkLibC();  // necessário se usar @cImport

// ERRO: Tipo errado na conversão
// const x: i32 = valor_c;  // use c_int, não i32

// CORRETO
const x: c_int = valor_c;

// ERRO: String Zig não termina em null para C
// const s = "texto"; // pode não ter sentinela 0
// CORRETO: usar literal com sentinela
const s: [:0]const u8 = "texto"; // terminado em 0
```

## Veja Também

- [Build System](/cheatsheets/build-system/) — Configurar linkagem C no build.zig
- [Ponteiros](/cheatsheets/ponteiros/) — Tipos de ponteiros e conversões
- [Strings](/cheatsheets/strings/) — Strings Zig vs strings C
- [Troubleshooting: Link C](/troubleshooting/zig-c-library-link/) — Problemas de linkagem
- [FAQ Ecossistema](/faq/faq-ecossistema/) — Bibliotecas C compatíveis com Zig
