# Calling C

### Calling C

One of Zig's design goals is direct interoperability with C.

A Zig program can call C functions without wrapper generators, external build tools, or foreign function interfaces layered on top of the language. Zig understands C calling conventions, C data layout, and C header files directly.

A small example is enough to begin.

Suppose we have this C source file:

```c
#include <stdio.h>

void greet(const char *name) {
    printf("hello, %s\n", name);
}
```

Save it as `greet.c`.

Now write a Zig program that calls it:

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

extern fn greet(name: [*:0]const u8) void;

pub fn main() void {
    greet("zig");
}
```

Build and run:

```sh
zig run main.zig greet.c
```

The output is:

```text
hello, zig
```

The important line is the declaration:

```zig
extern fn greet(name: [*:0]const u8) void;
```

`extern` says the function is defined outside Zig.

The declaration gives Zig enough information to call the function correctly:

- the function name
- the parameter types
- the return type
- the calling convention

The parameter type:

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

is a many-item pointer terminated by zero. This matches a C string:

```c
const char *
```

Zig does not have a separate built-in string type compatible with C. Instead, the programmer states the exact memory representation.

A Zig string literal:

```zig
"zig"
```

already contains a trailing zero byte when needed for C interoperation, so it can be passed directly here.

C functions that return integers work naturally.

This C source:

```c
int add(int a, int b) {
    return a + b;
}
```

can be called from Zig:

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

extern fn add(a: c_int, b: c_int) c_int;

pub fn main() void {
    const result = add(3, 4);
    std.debug.print("{d}\n", .{result});
}
```

Run it:

```sh
zig run main.zig add.c
```

The output is:

```text
7
```

Notice the type:

```zig
c_int
```

Zig provides C-compatible integer aliases:

| Zig type | C type |
|---|---|
| `c_char` | `char` |
| `c_short` | `short` |
| `c_int` | `int` |
| `c_long` | `long` |
| `c_longlong` | `long long` |

These types match the target platform's C ABI.

C pointers map naturally into Zig pointer types.

| C | Zig |
|---|---|
| `int *` | `*c_int` |
| `const char *` | `[*:0]const u8` |
| `void *` | `*anyopaque` |

Zig distinguishes several pointer kinds because the language tries to make memory usage explicit.

A normal Zig slice:

```zig
[]const u8
```

contains:

- a pointer
- a length

A C string does not contain a length. It depends on a terminating zero byte instead. For this reason, Zig uses different types for the two representations.

C functions may also be declared with explicit calling conventions:

```zig
extern "c" fn puts(s: [*:0]const u8) c_int;
```

The `"c"` calling convention matches the platform ABI used by C compilers.

In practice, ordinary `extern fn` declarations already default to the C ABI on supported targets.

A Zig program may link against:

- standalone C source files
- static libraries
- shared libraries
- operating system APIs

For example:

```sh
zig build-exe main.zig greet.c
```

or:

```sh
zig build-exe main.zig -lc
```

to link against the system C library.

The reverse direction is also possible: C code can call Zig functions.

A Zig function exported to C looks like this:

```zig
export fn square(x: c_int) c_int {
    return x * x;
}
```

`export` makes the symbol visible to external code.

Zig tries to make interoperability ordinary rather than exceptional. A C function declaration in Zig looks close to its original form, and the generated machine code follows the same ABI rules as a C compiler.

