> ## Documentation Index
> Fetch the complete documentation index at: https://docs.arcane-powered.com/sdk/llms.txt
> Use this file to discover all available pages before exploring further.

# C ABI

> FFI entry points for Unity, Unreal, and other native engines.

Minimal C ABI for engines that cannot call Rust directly. Build as `cdylib` or `staticlib`, then call init at launch with your portal public key.

## Functions

```c theme={null}
#include <stddef.h>

/* 0 = ok, 1 = bad public key arg, 2 = SdkError (see err_buf) */
int arcane_sdk_init(const char *game_id, char *err_buf, size_t err_len);

int arcane_check_ownership_offline(
    const char *game_id,
    char *err_buf,
    size_t err_len
);
```

The `game_id` parameter is the **portal public key** (NUL-terminated UTF-8).

| Function                         | Behavior                                                       |
| -------------------------------- | -------------------------------------------------------------- |
| `arcane_sdk_init`                | Default launch path — same as Rust `arcane_init`               |
| `arcane_check_ownership_offline` | Optional custom check — same as Rust `check_ownership_offline` |

On error code `2`, `err_buf` receives a truncated `code: message` string.

## Example

```c theme={null}
char err[512];
/* public key from Arcane portal */
int rc = arcane_sdk_init("pk_...", err, sizeof(err));
if (rc == 0) {
  /* Owned or DRM disabled — continue launch */
} else if (rc == 1) {
  /* Invalid arguments */
} else {
  /* See err for ticket_missing, ticket_expired, … */
}
```

## Safety notes

* Pointers must be valid for the duration of the call
* `err_buf` may be null or `err_len == 0` if you do not need the message
* Do not free strings owned by the SDK; only the caller-owned `err_buf` is written into

## Link

```bash theme={null}
cargo build --release
# artifacts: target/release/libarcane_sdk.{a,so,dylib} (platform-specific)
```
