Subsystem · Language bindings

Language bindings

Seven native DCPS APIs, all driven by the same wire format. No JNI, no P/Invoke, no thin wrappers — each binding is a first-class crate.

Learn

Learn — what is a language binding (PSM)?

DDS is defined at two levels. The PIM — Platform-Independent Model — describes Participant, Topic, Publisher, Subscriber, DataWriter, DataReader as abstract concepts. The PSM — Platform-Specific Mapping — maps those concepts onto a concrete programming language: which class, which method signature, which threading model, which error type.

OMG has ratified PSMs for C++ (DDS-PSM-Cxx 1.0) and Java (DDS-Java-PSM). For C#, Python, TypeScript and Rust the industry uses vendor-defined PSMs — every vendor invents their own, which is why moving an application from one vendor to another usually means rewriting all the binding code.

ZeroDDS ships seven native PSMs in one workspace. The OMG-defined C++ and Java PSMs are spec-conform; the C#, Python, TypeScript, Rust and C-FFI PSMs are vendor PSMs documented as ZeroDDS extensions. All seven sit on the same Pure-Rust core — no JNI, no P/Invoke, no transitive C dependencies.

Why

Why — why native bindings, not just one C-FFI?

The cheap option for a multi-language project is one C-FFI library plus thin wrappers in every other language. It compiles fast and looks clean from outside. The hidden cost shows up in production.

First, performance: every call across an FFI boundary serialises arguments, checks lifetimes, and pays a context-switch tax. For a hot-path DataWriter writing 10 kHz that is a measurable hit. Native bindings call directly into Rust functions with zero-cost type erasure.

Second, idiomatic surface: a Java developer expects @Override, AutoCloseable, virtual threads; a Python developer expects async-await, mypy-checkable types; a C# developer expects IDisposable, async/await with CancellationToken. A C-FFI wrapper can fake those — badly. A native binding renders them naturally.

Third, audit trail: when a Java auditor traces a security incident, they want to see Java source, not a JNI wrapper around an opaque C function. Native bindings make every layer auditable in the language of the consuming team.

Fourth, no JNI / no P/Invoke / no transitive C toolchain: ZeroDDS' Java is Pure Java (no native libraries), the C# is Pure C# (no DllImport). The whole binding compiles with the standard JDK / .NET SDK — no platform-specific .so / .dll to manage.

What

What we built

Eight binding crates, one core. Each crate is RC3-ready and ships with its own README, examples and spec-coverage report.

Crate Role Spec / target
dcps Core PIM OMG DDS 1.4 — the PIM that all language bindings sit on. Provides Participant, Publisher, Subscriber, Writer, Reader, QoS-Policy types.
dcps-async Async wrapper Async/await flavour of the core. Tokio-compatible. Shared by Rust and C# bindings.
rs Rust binding zerodds-rs — idiomatic Rust SDK, async/await, streams. Stable Rust 1.88+.
cpp C++17 binding OMG DDS-PSM-Cxx 1.0 — spec-conformant C++17 PSM. ABI-stable headers emitted by zerodds-idlc --cpp.
cs C# / .NET bindingVendor PSM. .NET 8 + netstandard2.1, async/await, IDisposable lifetime, NuGet-packageable.
java-omgdds Java binding OMG DDS-Java-PSM (org.omg.dds.*) — spec-conformant, Pure Java (no JNI). Records, sealed types, virtual threads.
py Python binding Vendor PSM. PyO3-Bindings für DCPS-API + @idl_struct-Decorator für Codegen-freien Topic-Pfad + AsyncIO-Wrapper. Wheels für CPython 3.8–3.14 (abi3-py38).
ts-node TypeScript (Node)Vendor PSM for Node.js. Full DCPS + WebSocket / gRPC bridge plumbing.
ts-wasmTypeScript (browser)Vendor PSM for browsers. WebSocket-only transport, no native sockets. Compiles to WASM.
zerodds-c-api C-FFI Stable C ABI in zerodds-c-api. Header pulls in libzerodds.so / zerodds.dll. For languages we do not ship native bindings for.
sys FFI helpers Internal FFI plumbing used by zerodds-c-api. Not consumed directly.

Spec coverage — by PSM

Two OMG PSMs and six vendor PSMs. The OMG ones are spec-conformant end-to-end; the vendor ones follow ZeroDDS conventions documented per language.

PSM Spec 5-Min Quickstart Implementation Tests Status
C++ PSM DDS-PSM-Cxx 1.0 C++ example → crates/cpp cpp/tests ✓ full
Java PSM DDS-Java-PSM Java example → crates/java-omgdds java-omgdds/test ✓ full
Rust PSM ZeroDDS vendor PSM → Rust example → crates/rs rs/tests ✓ RC3
C# / .NET PSM ZeroDDS vendor PSM → C# example → crates/cs cs/tests ✓ RC3
Python PSM ZeroDDS vendor PSM → Python example → crates/py py/python/tests ✓ RC3
TypeScript PSM (Node) ZeroDDS vendor PSM → Node example → crates/ts-node ts-node/tests ✓ RC3
TypeScript PSM (browser) ZeroDDS vendor PSM → Browser example → crates/ts-wasm ts-wasm/tests ✓ RC3
C-FFI ZeroDDS C ABI → C example → crates/zerodds-c-api zerodds-c-api/tests ✓ RC3
How

How — using the bindings

One install line per language, one or two-line ‘hello pub/sub’ example, links to the architecture doc and the man page.

ABI guarantees

Within a major version (1.x), wire-stable across every patch release. Source-stable within a minor (1.M.x). Breaking source changes only at major version boundaries (1 → 2). See the upgrade-guide topic for the matrix.

Upgrade guide →

Per-language pointers

Rust

cargo add zerodds-dcps zerodds-rs. Async via dcps-async. Stable Rust 1.88+.

cargo add zerodds-dcps zerodds-rs
C++

OMG DDS-PSM-Cxx 1.0. Headers emitted by zerodds-idlc --cpp. CMake integration shipped.

find_package(ZeroDDS REQUIRED)
target_link_libraries(my_app ZeroDDS::dcps)
C# / .NET

dotnet add package ZeroDDS.Dcps. .NET 8+, netstandard2.1, async/await.

dotnet add package ZeroDDS.Dcps
Java

OMG DDS-Java-PSM (org.omg.dds.*). Pure Java — no JNI, no native lib.

<dependency>org.zerodds:dcps:1.0.0</dependency>
Python

PyO3-Bindings für die DCPS-API plus AsyncIO-Wrapper und @idl_struct-Decorator für Codegen-freien Topic-Pfad. Wheels für CPython 3.8–3.14 (abi3-py38).

pip install zerodds
TypeScript

Two variants: Node.js (full DCPS + bridges) and browser bundle (WebSocket only).

npm install @zerodds/dcps
C-FFI

Stable C ABI. Link with -lzerodds. Header pulls everything from libzerodds.so / zerodds.dll.

#include <zerodds.h>