# Calling Zig from C

### Calling Zig from C

C can call Zig when the Zig function is exported with a C-compatible ABI.

The Zig function:

```zig
export fn add(a: c_int, b: c_int) c_int {
    return a + b;
}
```

`export` makes the symbol visible outside the Zig object file. The parameter and return types use C-compatible integer types, so C can call the function safely.

Put this in `math.zig`:

```zig
export fn add(a: c_int, b: c_int) c_int {
    return a + b;
}
```

Now write a C program:

```c
#include <stdio.h>

int add(int a, int b);

int main(void) {
    printf("%d\n", add(3, 4));
    return 0;
}
```

Build them together:

```sh
zig cc main.c math.zig -o main
```

Run it:

```sh
./main
```

The output is:

```text
7
```

The C declaration:

```c
int add(int a, int b);
```

must match the Zig declaration:

```zig
export fn add(a: c_int, b: c_int) c_int
```

The names must match. The argument types must match. The return type must match.

For simple C types, use Zig's C aliases:

```zig
c_char
c_short
c_int
c_long
c_longlong
c_uint
c_ulong
```

For pointers, export ordinary pointer-shaped data, not Zig-only structures.

This Zig function accepts a C string:

```zig
const std = @import("std");

export fn length(s: [*:0]const u8) c_int {
    const n = std.mem.len(s);
    return @intCast(n);
}
```

C can call it:

```c
#include <stdio.h>

int length(const char *s);

int main(void) {
    printf("%d\n", length("hello"));
    return 0;
}
```

A C string is not a Zig slice. It is a pointer to bytes ending in zero. That is why the Zig type is:

```zig
[*:0]const u8
```

Do not export a function like this to C:

```zig
export fn bad(s: []const u8) void {
    _ = s;
}
```

A Zig slice is two machine words: pointer and length. C does not know that type unless you define the same layout manually.

Use an explicit C-shaped interface instead:

```zig
export fn write_bytes(ptr: [*]const u8, len: usize) void {
    const bytes = ptr[0..len];
    _ = bytes;
}
```

C calls it as:

```c
void write_bytes(const unsigned char *ptr, size_t len);
```

Structs can cross the boundary when their layout is fixed.

```zig
const Point = extern struct {
    x: c_int,
    y: c_int,
};

export fn sum_point(p: Point) c_int {
    return p.x + p.y;
}
```

The matching C code:

```c
struct Point {
    int x;
    int y;
};

int sum_point(struct Point p);
```

The keyword `extern struct` tells Zig to use C layout rules. A normal Zig `struct` has layout chosen by Zig and must not be treated as a C struct.

The same rule applies to enums and unions. Use C-shaped declarations at the boundary. Convert to better Zig types inside the Zig code.

A common pattern is:

```zig
export fn api_function(raw_ptr: ?*anyopaque) c_int {
    if (raw_ptr == null) return -1;

    // Convert raw C-shaped inputs here.
    // Then call ordinary Zig code.
    return 0;
}
```

The exported layer should be small. It should check inputs, convert C data into Zig data, and return C-compatible results.

The rest of the program can remain ordinary Zig.

