# C and C++

A Gizlang program calls C and C++ code in its own process. You write no glue code and no build file: clang reads the
C or C++ file, and the `giz` command makes the module, compiles the code and links it.

| You have | Do this |
| --- | --- |
| A C or C++ source file | [Import the file](#import-a-c-file) as a module |
| A C library and its header | [Import a header of two lines](#use-a-c-library) |
| One function of a library | [Declare the function](#declare-one-c-function) |

`giz run`, `giz check`, `giz test` and `giz build` all work with C and C++ files. clang must be installed when you
build from a source checkout; an installed toolchain has its own clang.

## Import a C file

Put the C file beside the program and import it as you import a module.

```c title="stats.c"
#include <stddef.h>
#include <stdint.h>

#define STATS_VERSION 2

typedef struct { int32_t low; int32_t high; } Range;

/* The lowest and the highest byte of DATA. */
Range span(const uint8_t *data, size_t length) {
    Range r = { 255, 0 };
    for (size_t i = 0; i < length; i++) {
        if (data[i] < r.low) r.low = data[i];
        if (data[i] > r.high) r.high = data[i];
    }
    return r;
}

/* The count of BYTE in DATA. FIRST gets the index of the first one, or -1. */
size_t count(const uint8_t *data, size_t length, uint8_t byte, int64_t *first) {
    size_t n = 0;
    *first = -1;
    for (size_t i = 0; i < length; i++) {
        if (data[i] == byte) {
            if (n == 0) *first = (int64_t)i;
            n++;
        }
    }
    return n;
}
```

```gizlang run title="stats.giz"
import {STATS_VERSION, Range, span, count} from "./stats.c";

function report(data: bytes): void {
    const r: Range = span(data, u64(data.length));
    let first = 0;
    const n = count(data, u64(data.length), 97u, first);
    console.log(STATS_VERSION, r.low, r.high, n, first);
}

report(b"banana");
```

```text output
2 97 110 3 1
```

- The functions, structs, enums and simple macros of the file are the exports of the module. So are those of each
  file that it includes with `#include "..."`. A file that it includes with `#include <...>` is only read.
- `Range` is a record with the layout of the C struct. A struct goes in and out by value.
- `int64_t *first` is an out-parameter: pass a `let` local, and C writes it.
- A change of the C file, or of a file that it includes in quotes, compiles it again. Otherwise the object comes from
  the cache.
- A C error stops `giz check` with clang's message and the line in the C file.

## Use a C library

Write a header of two lines in the program's folder. `#pragma comment(lib, "NAME")` links the library: with the flags
of pkg-config when pkg-config knows NAME, else with `-lNAME`. `#include "..."` in quotes makes the functions of the
library's header the exports of the module.

```c
#pragma comment(lib, "zlib")
#include "zlib.h"
```

With that file saved as `zip.h`, the program calls zlib:

```typescript
import {crc32, zlibVersion} from "./zip.h";

console.log(crc32(0u, b"hello", 5u), zlibVersion());
```

## Use C++

A C++ file (`.cc`, `.cpp`, `.cxx`, `.hh`, `.hpp`, `.hxx`) is imported in the same way. It also links the C++ library.

```c++ title="counter.cpp"
#include <stdexcept>
#include <string>

namespace demo {
std::string greet(const std::string &name) { return "hello, " + name; }

int divide(int a, int b) {
    if (b == 0) throw std::invalid_argument("divide by zero");
    return a / b;
}

class Counter {
public:
    explicit Counter(int start) : count(start) {}
    void add(int n) { count += n; }
    int value() const { return count; }
private:
    int count;
};
}
```

```gizlang run title="counter.giz"
import * as Demo from "./counter.cpp";

const c = new Demo.Counter(5);
c.add(2);
console.log(Demo.greet("C++"), c.value());
c.close();
try {
    Demo.divide(1, 0);
} catch (e) {
    console.log(`caught ${e}`);
}
```

```text output
hello, C++ 7
caught divide by zero
```

- `std::string` and `std::string_view` are `string`.
- A class with members other than scalar and pointer fields is a record `{ handle: u64 }`, the address of the object.
  `new Name(...)` runs its first constructor, and its public methods are methods of the record. A static method is the
  function `Name_method`. `close()` deletes the object; call it once.
- A function that is not `noexcept` catches a C++ exception and throws its message as a `string`.
- The names of a namespace are the exports, without the namespace.

## Declare one C function

To call one function of a library, declare it. `from "LIBRARY"` links `-lLIBRARY`; without it, the function comes from
the C library.

```gizlang run title="hypot.giz"
declare function hypot(x: f64, y: f64): f64 effects {} from "m";

console.log(hypot(3.0, 4.0));
```

```text output
5
```

`effects {}` says that the function has no effects that Gizlang can see. Without a row, the effects are
`{io, fail}`. Gizlang cannot see into C, so the row is your promise.

`giz bind HEADER LIBRARY NAME...` writes these declarations from a C header
([the tools](../internals/tools.md#c-and-typescript-bindings)).

## Types

The types of an imported file and of a declaration are the same:

| Gizlang | C |
| --- | --- |
| `i8` to `i64`, `u8` to `u64`, `f32`, `f64`, `bool` | The integer, float or `bool` of that width. A value that does not fit the parameter fails (R003). |
| `string` | A `const char *` to a copy that ends with NUL. A string that contains NUL fails (R003). As the result, the returned text is copied. NULL is `""`. Invalid UTF-8 fails. |
| `bytes` | A pointer to the first byte, or NULL when empty. Pass the length as a separate argument. |
| A record of the scalars above | A pointer to a C struct with those fields in order. An imported file also passes it by value. |
| `mut` scalar | A pointer to it: an out-parameter of C. It is read back into the local after the call. |
| `mut bytes`, `mut` record | C writes into the buffer or struct of the local. |
| `u64` | Any other pointer, for example a handle that C returns (`sqlite3 *`). |
| `(a: T, ...) => R` | A C function pointer. The argument names a top-level function whose types are the value types of the signature (`i64` for `i32`). A maximum of 8 scalar parameters. `R` is a scalar or `void`. |

In an imported file, these C types also map:

- `int64_t`, `size_t` and the other names of `<stdint.h>` and `<stddef.h>` are their scalars.
- `void *` is a `u64`. A pointer to bytes (`char *`, `uint8_t *`) is `bytes`. A pointer to another scalar is a `mut`
  argument.
- The names of an enum, and a macro of an integer, a float or a string, are constants.

These are not exported, and a comment in the generated module says why: variadic functions, templates, operators,
unions, structs with fields that are not scalars, and `long double`. To use one, write a small C or C++ function in
your file that calls it with the types above.

## Calls and callbacks

- A `mut` argument is a `let` local. Module state cannot be passed as `mut`.
- A callback runs on the calling task. After a fault inside a callback, later calls return 0 to C without running.
  The fault fails the caller of the C function when C returns.
- A callback result that does not fit its C type fails (R003).
- A callback receives pointers as `u64`. To read through one, declare a C function such as `memcpy`.
- A C call that can fail (R003, a string with NUL, a failed callback) makes the function that calls it fail, as any
  other fault does.

## Authority

A C function has all the authority of the process, and the checker cannot see into it.

- Only the application can declare a C function: its entry module, or a package module whose manifest entry grants
  the library (`"native": ["m"]`, or `"c"` for functions without `from`). Any other declaration is `E_MODULE`.
- The manifest of a dependency can grant only what its parent granted to it (the same `"native"` on its entry in
  `dependencies`). If not, the package is `E_PACKAGE`.
- The CLI grants an imported C or C++ file the object that it built, so its functions run. An `"imports"` limit
  decides which modules may import it ([packages](packages.md)).
- Symbols that start with `gizlang_` are runtime services. Only the standard library declares them.

How the CLI reads, compiles and caches the files is in [the system internals](../internals/system.md#native-functions).
