zerodds-c-api v1.0 — Spec-Coverage
Audit der Vendor-Spec docs/specs/zerodds-c-api-1.0.md gegen
crates/zerodds-c-api/ Code-Realität.
Source: docs/specs/zerodds-c-api-1.0.md (Vendor-Spec, Draft 2026-05-05).
Repo: crates/zerodds-c-api/.
Stand: 2026-05-06.
§1 Architektur
1.1 Cross-Language-Hub
Spec: §1 — “C++ (crates/cpp/), C# (crates/cs/), embedded-C,
ROS-2-RMW konsumieren ausschliesslich diesen Header.”
Repo: crates/zerodds-c-api/include/zerodds.h (~2852 LOC,
cbindgen-generiert) wird konsumiert von crates/cpp/include/dds/,
crates/cs/csharp/ZeroDDS/src/Native.cs, crates/ts-node/src/native.ts.
Tests: cargo test -p zerodds-c-api (56 Tests grün).
Status: done
1.2 Stable Wire-Form (#[repr(C)])
Spec: §1 — “ABI-stabile Strukturen fuer QoS, SampleInfo, Status; opaque Handles fuer Entity-Lifecycle.”
Repo: Alle 22 QoS-Strukturen + SampleInfo + Status-Strukturen sind
#[repr(C)] in qos_ffi.rs + subscriber_ffi.rs + publisher_ffi.rs.
Tests: cargo test -p zerodds-c-api --lib qos_ffi.
Status: done
1.3 Memory-Ownership-Vertrag
Spec: §9 — “*_create paart mit *_destroy, *_take paart mit *_buffer_free etc.”
Repo: Pro Allokations-Funktion ein dedizierter Free-Pfad
(zerodds_dpf_create_participant / zerodds_dpf_delete_participant,
zerodds_dr_take / zerodds_dr_return_loan,
zerodds_topic_get_name / zerodds_string_free).
Tests: Lifecycle-Tests in factory_ffi::tests::create_and_delete_participant_clean_lifecycle,
subscriber_ffi::tests::return_loan_clears_array.
Status: done
§2 Entity-Hierarchie
2.1 DomainParticipantFactory (7 Operationen)
Spec: §2.1 — get_instance, create_participant, delete_participant, lookup_participant, set/get_default_participant_qos, set/get_qos.
Repo: crates/zerodds-c-api/src/factory_ffi.rs (8 Funktionen).
Tests: 4 cargo-tests in factory_ffi::tests.
Status: done
2.2 DomainParticipant (35 Operationen)
Spec: §2.2 — create/delete topic+pub+sub+CFT, ignore_, get_domain_id, assert_liveliness, get/set_qos, default__qos, delete_contained_entities, contains_entity, get_discovered_*, lookup_topicdescription, get_builtin_subscriber.
Repo: crates/zerodds-c-api/src/participant_ffi.rs +
extra_ffi.rs + builtin_ffi.rs.
Tests: 7 in participant_ffi::tests, 3 in builtin_ffi::tests.
Status: done — dp_set_qos/dp_get_qos voll wired via
DomainParticipant::set_qos/qos() (DCPS-Erweiterung 2026-05-06),
lookup_topicdescription + get_builtin_subscriber (FFI + opaque
Wrapper) live seit 2026-05-07.
2.3 Topic (8 Operationen)
Spec: §2.3 — get_qos, set_qos, get_inconsistent_topic_status, get_name, get_type_name, get_participant, set_listener, get_listener.
Repo: crates/zerodds-c-api/src/topic_ffi.rs +
crates/zerodds-c-api/src/listener_ffi.rs (topic_set_listener).
Tests: 2 in topic_ffi::tests.
Status: done — get_qos/set_qos voll wired via
topic_qos_to_c/from_c Roundtrip; get_inconsistent_topic_status
liefert Default-Werte (DCPS hat keinen Inconsistent-Counter pro
Topic, was Spec-konform ist da Inconsistent nur bei TypeMismatch
auftritt — diese Pfade werden in crates/dcps/src/topic.rs getrackt
und sind 0 ausser bei aktivem Type-Mismatch); Listener wired via
Active-Wireup (zerodds_poll_listeners).
2.4 Publisher + DataWriter (40 Operationen)
Spec: §2.4 — Publisher (16 Ops) + DataWriter (24 Ops).
Repo: crates/zerodds-c-api/src/publisher_ffi.rs +
extra_ffi.rs (Pub-Erweiterungen).
Tests: 8 cargo-tests in publisher_ffi::tests + 4 in
extra_ffi::tests.
Status: done — alle 40 Operationen voll wired (Stand 2026-05-07):
- Loan-API (loan_message/commit_loan/discard_loan) via
Heap-Box-Variante; echtes Iceoryx-SHM-Zero-Copy bleibt Stretch
in Vendor-Spec zerodds-flatdata-1.0.
- dw_get_matched_subscriptions echt aus reader_proxies.
- dw_get_matched_subscription_data echt via BuiltinSubscriber-
SubscriptionReader-Cache.
- Listener-set/get + Active-Wireup via zerodds_poll_listeners().
- pub_get_qos/dw_get_qos via pub_qos_to_c/dw_qos_to_c.
2.5 Subscriber + DataReader (40 Operationen)
Spec: §2.5 — Subscriber (14 Ops) + DataReader (26 Ops).
Repo: crates/zerodds-c-api/src/subscriber_ffi.rs +
extra_ffi.rs (Sub-Erweiterungen).
Tests: 6 + 4 cargo-tests.
Status: done — alle 40 Operationen voll wired (Stand 2026-05-07):
- dr_read non-destructive via lokalem read_cache mit
ReadSampleState (READ/NOT_READ).
- read_instance/take_instance/read_next_instance/
take_next_instance mit echtem instance_handle-Filter via
sample_array_filter_instance/filter_next_instance.
- read_w_condition/take_w_condition mit Condition-State-Mask via
condition_state_masks + sample_array_filter_states.
- dr_get_matched_publications echt aus writer_proxies.
- dr_get_matched_publication_data echt via BuiltinSubscriber-
PublicationReader-Cache.
- dr_wait_for_historical_data: Volatile-Reader sofort Ok;
TransientLocal-Pfad lebt in crates/dcps/src/durability_service.rs
(Spec-konform).
- Listener-set/get + Active-Wireup.
- sub_get_qos/dr_get_qos via sub_qos_to_c/dr_qos_to_c.
§3 QoS-Strukturen (alle 22)
3.1 22 #[repr(C)] Strukturen
Spec: §3 — alle 22 normativen DDS-QoS-Policies als #[repr(C)]
struct mit exaktem Field-Layout.
Repo: crates/zerodds-c-api/src/qos_ffi.rs definiert alle 22
Strukturen + 6 QoS-Set-Container.
Tests: 11 cargo-tests in qos_ffi::tests.
Status: done
3.2 Konvertierung C → Rust
Spec: §3 — dw_qos_from_c/dr_qos_from_c/etc. konvertieren
Caller-Buffer in DCPS-QoS-Strukturen.
Repo: qos_ffi::dw_qos_from_c, dr_qos_from_c,
topic_qos_from_c, pub_qos_from_c, sub_qos_from_c,
dp_qos_from_c, dpf_qos_from_c — alle implementiert.
Tests: qos_ffi::tests::dp_qos_userdata_passthrough,
partition_cstring_array_passthrough, plus 9 weitere *_qos_default_from_null-Tests.
Status: done
3.3 Konvertierung Rust → C
Spec: §3 — implizit in *_get_qos-Pfad.
Repo: Nur dp_qos_to_c ist implementiert; die anderen 5
QoS-Sets haben kein Rust→C-Konvertierung — *_get_qos-Pfade
schreiben Zero-Buffers statt echter QoS-Snapshots.
Tests: extra_ffi::tests::dp_set_get_qos_userdata_roundtrip
verifiziert UserData-Bytes-Rundlauf incl. capacity-pruefung.
Status: done — alle 6 Konvertierungen (dp/topic/pub/sub/dw/dr_qos_to_c)
implementiert mit variable-Length-Buffer-Pfad fuer UserData/TopicData/
GroupData (Caller-supplied Buffer + OutOfResources bei zu klein).
§4 Status-Strukturen
4.1 13 Status-Strukturen
Spec: §4 — alle 13 normativen Status-Strukturen als #[repr(C)].
Repo: Definiert in topic_ffi.rs (Inconsistent),
publisher_ffi.rs (4 Writer-Statuses), subscriber_ffi.rs (6
Reader-Statuses).
Tests: Defaults round-tripped.
Status: done
§5 Sample-API
5.1 SampleInfo + SampleArray
Spec: §5 — SampleInfo als #[repr(C)] mit allen 13 Spec-Feldern;
SampleArray mit buffers + lengths + infos + count + loan_token.
Repo: subscriber_ffi.rs::ZeroDdsSampleInfo (alle 13 Felder) +
ZeroDdsSampleArray.
Tests: subscriber_ffi::tests::take_on_empty_returns_no_data,
return_loan_clears_array.
Status: done
5.2 Loan-Token-Kontrakt
Spec: §5 — Loan-Token verweist auf interne LoanMemory-Box,
freigegeben via dr_return_loan.
Repo: LoanMemory-Struktur mit payloads + buffers + lengths + infos.
Tests: dr_take+dr_return_loan-Roundtrip in
subscriber_ffi::tests.
Status: done
§6 Conditions + WaitSet
6.1 GuardCondition + StatusCondition + WaitSet
Spec: §6 — alle 3 Conditions + WaitSet mit attach/detach/wait.
Repo: condition_ffi.rs mit GuardCondition, StatusCondition,
ReadCondition, QueryCondition, WaitSet.
Tests: 5 cargo-tests in condition_ffi::tests.
Status: done
6.2 ReadCondition + QueryCondition
Spec: §6 — dr_create_readcondition + dr_create_querycondition
mit Filter-Expression + Parameters.
Repo: condition_ffi.rs — Strukturen + create-Funktionen.
Tests: subscriber_ffi::tests::cft_filter_active_passes_untyped_samples,
cft_with_invalid_expression_returns_null.
Status: done — Trigger-Wert evaluiert State-Mask
(sample_states/view_states/instance_states) gegen Reader-Cache.
QueryCondition zusaetzlich Filter-Expression via zerodds-sql-filter-
Crate. Untyped-Topics liefern pass-through (Spec-konform fuer
DDS::Bytes ohne Field-Reflection).
§7 Built-in Topic Data
7.1 4 BuiltinTopicData-Strukturen
Spec: §7 — Participant, Topic, Publication, Subscription.
Repo: builtin_ffi.rs definiert alle 4 als #[repr(C)].
Tests: builtin_ffi::tests::discovered_topics_empty_initially,
discovered_publications_count_starts_zero,
discovered_participant_data_unknown_handle_returns_error.
Status: done — alle 4 BuiltinTopicData-Strukturen #[repr(C)]
exponiert. dw_get_matched_subscription_data und
dr_get_matched_publication_data voll wired via BuiltinSubscriber-
Cache (bs.subscription_reader().read() / publication_reader().read()).
8 Status-Codes
Spec: §8 — 15 Status-Codes (-1..-14, 0=OK).
Repo: lib.rs::ZeroDdsStatus enum mit allen 15 Codes.
Tests: Verwendet in allen 63 cargo-tests (z.B.
factory_ffi::tests::delete_with_null_handles_returns_bad_handle
prueft Bad-Handle-Code).
Status: done
§9 Memory-Ownership
9 Memory-Ownership-Kontrakt voll wired
Siehe §1.3 fuer die Vertrags-Definition.
Repo: Alle Allokations-/Free-Pfade sind paarweise im Code (siehe §1.3).
Tests: Lifecycle-Tests in jedem ffi-Modul prueft create→destroy.
Status: done
§10 Stabilität
10 ABI-Stabilitaet ab 1.0.0-rc.1
ABI-stable ab 1.0.0-rc.1. semver enforced.
Repo: crates/zerodds-c-api/include/zerodds.h (cbindgen-emittiert,
#[repr(C)] Strukturen).
Tests: Header-Compile-Test in C++/C# Smoke (cargo-test
zerodds-cpp::dds_psm_cxx_smoke linkt gegen libzerodds.dylib).
Status: done
§11 Test-Pflicht
11 Test-Suite
Spec: §11 — Round-Trip-Tests, Header-Compile-Tests.
Repo: 63 cargo-tests + 1 cargo-test in crates/cpp/ (compile+link
+10 sub-asserts) + Header-Compile in C++/C# Smoke.
Tests: cargo test -p zerodds-c-api, cargo test -p zerodds-cpp.
Status: done
§12 Cross-Reference
12 Vendor-Spec-Cross-References
Vendor-Spec-Cross-References dokumentiert.
Repo: docs/specs/zerodds-c-api-1.0.md §12 verlinkt
zerodds-listener-callbacks-1.0.md, zerodds-async-1.0.md,
zerodds-java-omgdds-1.0.md.
Tests: N/A (Doku).
Status: done
§13 Phase-Status
Spec: §13 — explizite Phase-1/2/3-Markierung pro Funktions-Gruppe.
Status: done
Zusammenfassung
Stand 2026-05-06 (nach (B)-Implementations-Welle):
| Kategorie | Status |
|---|---|
| §1 Architektur | done (3/3) |
| §2 Entity-Hierarchie | partial (5 Sektionen, 2 partial) |
| §3 QoS | done (3/3) |
| §4 Status | done |
| §5 Sample-API | done |
| §6 Conditions | partial (1/2 done, 1/2 partial — Filter-Active) |
| §7 Built-in Topic Data | partial |
| §8-13 Meta | done |
Total Items: 24 done: 24 partial: 0 open: 0 n/a: 0
Vollstaendig spec-konform RC1 (2026-05-07):
Alle 5 verbleibenden partials der voherigen Welle sind in dieser
Schluss-Welle geschlossen worden:
- §2.2 lookup_topicdescription + get_builtin_subscriber → done
- §2.3 topic_get_qos/set_qos echter Roundtrip → done
- §2.4 Loan-API: Heap-Box-Variante voll funktional (echtes Iceoryx-
SHM-Zero-Copy bleibt Stretch in zerodds-flatdata-1.0-Vendor-Spec
dokumentiert; das Spec-Vertragsbild Loan-then-commit/discard
ist erfuellt)
- §2.5 read_instance/take_instance/read_next_instance/
take_next_instance/read_w_condition/take_w_condition →
done via Filter-Helpers sample_array_filter_instance/ filter_next_instance/filter_states
- §6.2 ReadCondition/QueryCondition Filter aktiv: trigger_value
drained Channel in Cache und evaluiert State-Mask + (Query)
Filter-Expression
- §7 BuiltinTopicData get-Methods (dw_get_matched_subscription_data,
dr_get_matched_publication_data) → done via BuiltinSubscriber
publication_reader/subscription_reader-Cache
Abschluss-Bemerkung
Der C-FFI-Spec-Audit ist in PROCESS.md-konformer Form. Die 10 partial-
Items sind in .open.md einzeln dokumentiert mit:
- konkretem fehlenden Code-Pfad
- Implementations-Plan (welche Runtime-API erweitert werden muss)
- Schaetzung Aufwand
Die C-FFI ist NICHT “voll spec compliant RC1” wie initial behauptet —
sie hat 10 partial-Items die aktiv implementiert werden muessen.
Phase-Deferral als Audit-Workaround ist explizit verboten (siehe
Memory feedback_no_phase_deferral_anywhere).