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.
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.
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.
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.