# snapdir-ffi

The **C ABI layer** (`cdylib` + `staticlib`) that exposes the
[`snapdir-api`](../snapdir-api) facade to every non-Rust language binding:
Go (CGo), C/C++, Zig, and Java (JDK Foreign Function API).

The public C surface is declared in **`include/snapdir.h`** (cbindgen-generated,
C99 — never edit by hand; it is regenerated by `cargo build -p snapdir-ffi`).

It is part of the snapdir project. Full documentation, the CLI, and the available
storage backends are at **[snapdir.org](https://snapdir.org)**; the source lives in
the [canonical repository](https://github.com/snapdir/snapdir).

## ABI version

```c
#define SNAPDIR_ABI_VERSION 1
```

`SNAPDIR_ABI_VERSION` starts at `1` and is bumped **only** on a breaking C-ABI
change.  It is deliberately decoupled from the crate semantic version.

## Binary artifacts

| Artifact | Use case |
|---|---|
| `libsnapdir_ffi.so` / `libsnapdir_ffi.dylib` | cdylib — Zig `@cImport`, JNA, `dlopen` |
| `libsnapdir_ffi.a` | staticlib — CGo static linking |

## Minimal C usage

```c
#include "snapdir.h"
#include <stdio.h>

int main(void) {
    /* Optional: pre-warm the async runtime.  All blocking fns init lazily. */
    snapdir_init();

    SnapdirError *err = NULL;
    char *id = snapdir_id("/path/to/dir", NULL /* ManifestOptions */, &err);
    if (!id) {
        fprintf(stderr, "[%s] %s\n",
                snapdir_error_code(err),
                snapdir_error_message(err));
        snapdir_error_free(err);
        return 1;
    }
    printf("snapshot id: %s\n", id);
    snapdir_string_free(id);   /* ← every returned char* must be freed this way */
    return 0;
}
```

### Memory contract

Every `char *` returned by the library is heap-allocated by Rust and must be
freed with **`snapdir_string_free(ptr)`** (never with the system `free()`).
`snapdir_string_free(NULL)` is a safe no-op.

Errors are reported through an `out-parameter` (`SnapdirError **err_out`).  Free
each non-NULL error exactly once with **`snapdir_error_free(err)`**.
`snapdir_error_free(NULL)` is a safe no-op.

See `docs/rust-port/C_ABI.md` in the repository for the full memory contract,
the complete function reference, and binding-author guidance.

## Linking

### Dynamic (`cdylib`)

```sh
cc my_app.c -I/path/to/snapdir/include \
   -L/path/to/target/release \
   -lsnapdir_ffi -lpthread -ldl -lm \
   -o my_app
```

### Static (`staticlib`)

```sh
cc my_app.c -I/path/to/snapdir/include \
   /path/to/target/release/libsnapdir_ffi.a \
   -lpthread -ldl -lm \
   -o my_app
```

### pkg-config (future)

A `snapdir-ffi.pc` pkg-config file will be generated in a future release.
Until then, use the paths above or the `include/snapdir.h` header directly.

## License

MIT OR Apache-2.0
