Binding · C-FFI

C-FFI — in 5 Minuten zum ersten Sample

Stable C ABI über zerodds.h (cbindgen-generiert, ~2850 LOC). Wird von C++, C#, Python (ctypes-Pfad) und anderen Bindings konsumiert. Direkt nutzbar von Go, Zig, Ada, MATLAB, Erlang, OCaml, Haskell, Crystal — überall wo C-Interop läuft.

Header: crates/zerodds-c-api/include/zerodds.h Linking: -lzerodds -lpthread -ldl -lm Status: ✓ RC3 · Vendor-Spec

5-Minuten-Quickstart (C)

1 · libzerodds bauen

git clone https://github.com/zero-objects/zero-dds.git
cd zero-dds
cargo build --release -p zerodds-c-api
# target/release/libzerodds.{so,dylib,dll}
# crates/zerodds-c-api/include/zerodds.h

2 · Pub/Sub (hello.c)

#include "zerodds.h"
#include <stdio.h>
#include <string.h>
#include <unistd.h>

int main(void) {
    printf("zerodds version: %s\n", zerodds_version());

    struct zerodds_ZeroDdsRuntime *rt = zerodds_runtime_create(0);
    if (!rt) return 1;

    struct zerodds_ZeroDdsWriter *w =
        zerodds_writer_create(rt, "Chatter", "RawBytes", 1 /* reliable */);
    struct zerodds_ZeroDdsReader *r =
        zerodds_reader_create(rt, "Chatter", "RawBytes", 1);

    zerodds_writer_wait_for_matched(w, 1, 5000);
    zerodds_reader_wait_for_matched(r, 1, 5000);

    const char *payload = "hello";
    zerodds_writer_write(w, (const uint8_t*)payload, strlen(payload));

    sleep(1);

    uint8_t buf[64];
    size_t n;
    while ((n = zerodds_reader_take_into(r, buf, sizeof(buf))) > 0) {
        printf("got: %.*s\n", (int)n, buf);
    }

    zerodds_reader_destroy(r);
    zerodds_writer_destroy(w);
    zerodds_runtime_destroy(rt);
    return 0;
}

▶ Runnable example: c-ffi-hello

3 · Bauen + laufen

gcc -O2 -I crates/zerodds-c-api/include \
    -L target/release \
    -o hello hello.c \
    -lzerodds -lpthread -ldl -lm
LD_LIBRARY_PATH=target/release ./hello
# got: hello

Installation

System-Pakete

# Ubuntu/Debian
sudo apt install ./libzerodds_1.0.0-rc.3_amd64.deb libzerodds-dev_1.0.0-rc.3_amd64.deb
# Headers in /usr/include/zerodds/, libs in /usr/lib/

# Fedora/RHEL
sudo dnf install ./libzerodds-1.0.0-rc.3.x86_64.rpm libzerodds-devel-...

Aus dem Source

cargo build --release -p zerodds-c-api
# cdylib in target/release/libzerodds.{so,dylib,dll}
# staticlib in target/release/libzerodds.a

ABI-Stabilität

Alle zerodds_*-Funktionen in zerodds.h sind ABI-stable über patch-Versionen (1.0.x). Minor-Bumps (1.x → 1.y) können Funktionen hinzufügen, aber nicht ändern. Major-Bumps (1 → 2) dürfen Breaking-Changes.

Header wird mit cbindgen aus Rust generiert. Verifikation per CI gegen ein Reference-Header in crates/zerodds-c-api.

Vendor-Spec: zerodds-c-api 1.0 →

Andere Sprachen via C-FFI

Jede Sprache mit C-Interop kann libzerodds direkt nutzen. Wir liefern keine offiziellen Wrapper für diese, aber die Quickstart-Pattern sind kurz.

Go (via cgo)

/*
#cgo CFLAGS: -I/usr/include/zerodds
#cgo LDFLAGS: -lzerodds -lpthread -ldl -lm
#include "zerodds.h"
*/
import "C"

func main() {
    rt := C.zerodds_runtime_create(0)
    defer C.zerodds_runtime_destroy(rt)
    // ...
}

Zig

const c = @cImport({ @cInclude("zerodds.h"); });
const rt = c.zerodds_runtime_create(0);
defer c.zerodds_runtime_destroy(rt);

Python (ohne maturin, ctypes-Pfad)

from zerodds.loader import Runtime, Writer, Reader

rt = Runtime(domain_id=0)
w = Writer(rt, topic="Chatter", type_name="RawBytes", reliable=True)
# ...

Pure-ctypes-Loader liegt in crates/py/python/zerodds/loader.py. Folgt der gleichen Konvention wie der Rust-PyO3-Pfad, braucht aber kein maturin.

Andere

Ada (gnatcoll-bindings), MATLAB (loadlibrary + calllib), Erlang/Elixir (NIF mit erl_nif.h-Wrapper), Crystal (lib zerodds), Haskell (FFI mit foreign import ccall), OCaml (ctypes), Ruby (Fiddle). Alle folgen dem gleichen Pattern: Header inkludieren, Bibliothek linken, Funktionen direkt rufen.

Binding · C-FFI

C-FFI — first sample in 5 minutes

A stable C ABI via zerodds.h (cbindgen-generated, ~2850 LOC). Consumed by C++, C#, Python (the ctypes path) and other bindings. Directly usable from Go, Zig, Ada, MATLAB, Erlang, OCaml, Haskell, Crystal — anywhere C interop runs.

Header: crates/zerodds-c-api/include/zerodds.h Linking: -lzerodds -lpthread -ldl -lm Status: ✓ RC3 · vendor spec

5-minute quickstart (C)

1 · Build libzerodds

git clone https://github.com/zero-objects/zero-dds.git
cd zero-dds
cargo build --release -p zerodds-c-api
# target/release/libzerodds.{so,dylib,dll}
# crates/zerodds-c-api/include/zerodds.h

2 · Pub/sub (hello.c)

#include "zerodds.h"
#include <stdio.h>
#include <string.h>
#include <unistd.h>

int main(void) {
    printf("zerodds version: %s\n", zerodds_version());

    struct zerodds_ZeroDdsRuntime *rt = zerodds_runtime_create(0);
    if (!rt) return 1;

    struct zerodds_ZeroDdsWriter *w =
        zerodds_writer_create(rt, "Chatter", "RawBytes", 1 /* reliable */);
    struct zerodds_ZeroDdsReader *r =
        zerodds_reader_create(rt, "Chatter", "RawBytes", 1);

    zerodds_writer_wait_for_matched(w, 1, 5000);
    zerodds_reader_wait_for_matched(r, 1, 5000);

    const char *payload = "hello";
    zerodds_writer_write(w, (const uint8_t*)payload, strlen(payload));

    sleep(1);

    uint8_t buf[64];
    size_t n;
    while ((n = zerodds_reader_take_into(r, buf, sizeof(buf))) > 0) {
        printf("got: %.*s\n", (int)n, buf);
    }

    zerodds_reader_destroy(r);
    zerodds_writer_destroy(w);
    zerodds_runtime_destroy(rt);
    return 0;
}

▶ Runnable example: c-ffi-hello

3 · Build + run

gcc -O2 -I crates/zerodds-c-api/include \
    -L target/release \
    -o hello hello.c \
    -lzerodds -lpthread -ldl -lm
LD_LIBRARY_PATH=target/release ./hello
# got: hello

Installation

System packages

# Ubuntu/Debian
sudo apt install ./libzerodds_1.0.0-rc.3_amd64.deb libzerodds-dev_1.0.0-rc.3_amd64.deb
# headers in /usr/include/zerodds/, libs in /usr/lib/

# Fedora/RHEL
sudo dnf install ./libzerodds-1.0.0-rc.3.x86_64.rpm libzerodds-devel-...

From source

cargo build --release -p zerodds-c-api
# cdylib in target/release/libzerodds.{so,dylib,dll}
# staticlib in target/release/libzerodds.a

ABI stability

All zerodds_* functions in zerodds.h are ABI-stable across patch versions (1.0.x). Minor bumps (1.x → 1.y) may add functions but not change them. Major bumps (1 → 2) may make breaking changes.

The header is generated from Rust with cbindgen. Verified in CI against a reference header in crates/zerodds-c-api.

Vendor spec: zerodds-c-api 1.0 →

Other languages via C-FFI

Any language with C interop can use libzerodds directly. We don't ship official wrappers for these, but the quickstart patterns are short.

Go (via cgo)

/*
#cgo CFLAGS: -I/usr/include/zerodds
#cgo LDFLAGS: -lzerodds -lpthread -ldl -lm
#include "zerodds.h"
*/
import "C"

func main() {
    rt := C.zerodds_runtime_create(0)
    defer C.zerodds_runtime_destroy(rt)
    // ...
}

Zig

const c = @cImport({ @cInclude("zerodds.h"); });
const rt = c.zerodds_runtime_create(0);
defer c.zerodds_runtime_destroy(rt);

Python (without maturin, the ctypes path)

from zerodds.loader import Runtime, Writer, Reader

rt = Runtime(domain_id=0)
w = Writer(rt, topic="Chatter", type_name="RawBytes", reliable=True)
# ...

A pure-ctypes loader lives in crates/py/python/zerodds/loader.py. It follows the same convention as the Rust PyO3 path but needs no maturin.

Others

Ada (gnatcoll bindings), MATLAB (loadlibrary + calllib), Erlang/Elixir (a NIF with an erl_nif.h wrapper), Crystal (lib zerodds), Haskell (FFI with foreign import ccall), OCaml (ctypes), Ruby (Fiddle). All follow the same pattern: include the header, link the library, call the functions directly.