Skip to content
Quickstarts

C ABI & Dart quickstart

Use the plain-C ForestVPN client surface — one header, one shared library — from C, or generate Dart bindings for Flutter.

The lowest-level client surface is the forestvpn-client-ffi crate: the full ForestVPN client engine compiled to a shared library with a plain-C header at forestvpn-sdk/crates/forestvpn-client-ffi/include/forestvpn_client.h. If your language can call C, it can drive ForestVPN.

Honest distribution note: the library builds from source — there is no binary download and no pub.dev package for the Dart path yet.

Prerequisites

  • The Rust toolchain (rustup.rs)
  • A C compiler (cc)
  • A checkout of the ForestVPN repository

1. Get the source and build the library

git clone [email protected]:forestvpn/forestvpn.git
cd forestvpn/forestvpn-sdk
cargo build -p forestvpn-client-ffi --release

The crate's library name is forestvpn, so this produces target/release/libforestvpn.dylib (macOS), .so (Linux), or forestvpn.dll (Windows), alongside a static library.

2. First call: open a client, read status

first-call.c
#include <stdio.h>
#include <stdlib.h>

#include "forestvpn_client.h"

int main(void) {
  printf("ForestVPN client C ABI v%u\n", fvpn_abi_version());

  FvpnClient *client = NULL;
  int32_t rc = fvpn_client_open("/tmp/forestvpn-quickstart-state", &client);
  if (rc != FVPN_OK) {
    char message[512];
    fvpn_last_error_message(message, sizeof message);
    fprintf(stderr, "open failed (%d): %s\n", rc, message);
    return 1;
  }

  char *status_json = NULL;
  rc = fvpn_client_status_json(client, &status_json);
  if (rc == FVPN_OK) {
    printf("status: %s\n", status_json);
    fvpn_string_free(status_json);
  }

  fvpn_client_close(client);
  return rc == FVPN_OK ? 0 : 1;
}

Every fallible call returns an FvpnStatus (FVPN_OK on success); on failure, fvpn_last_error_message copies a human-readable message. Strings the library allocates come back through out-parameters and are released with fvpn_string_free.

3. Compile and run

From the repository root:

cc -I forestvpn-sdk/crates/forestvpn-client-ffi/include \
   first-call.c \
   -L forestvpn-sdk/target/release -lforestvpn \
   -o first-call
./first-call

Expected output: the ABI version line, then the client's status document as JSON.

Dart / Flutter

The header is written to be consumed directly by package:ffigen: every long-running call has an async variant that takes a Dart NativePort + request id (for example fvpn_client_status(client, dart_port, request_id) next to the synchronous fvpn_client_status_json), so results post back to your isolate without blocking. Point ffigen at forestvpn_client.h from your Flutter project and ship the step-1 library with your app bundle.

Verified by

scripts/quickstart-verify/c-ffi.sh — compiles this page's snippet against the real header (cc -fsyntax-only -Wall -Werror) on every run, so the functions shown here are guaranteed to exist with these signatures.