Onda C API reference
Use libonda to compile Onda programs and run them inside a native C or C++ application. The
library manages processor storage and validates bindings; your application supplies audio memory
and schedules processing calls.
Static and shared libraries expose the same API through
onda.h. Use the
Processor API when you want to link a compiled
processor directly without the Onda runtime.
Linking
Release SDKs contain both library variants and a CMake package:
find_package(Onda CONFIG REQUIRED)
target_link_libraries(my_host PRIVATE Onda::Shared)
# Or link the self-contained static library:
target_link_libraries(my_host PRIVATE Onda::Static)
Point CMAKE_PREFIX_PATH at the extracted SDK. Both imported targets provide the include directory.
Onda::Static also carries its platform system-library requirements. When using Onda::Shared, the
application must deploy onda.dll, libonda.so, or libonda.dylib in its normal runtime search
path.
Direct C and C++ users include the same header:
#include <onda.h>
The declarations have C linkage when included from C++.
Minimal host
This example compiles a processor, creates and initializes an instance, binds one output, and processes one complete block:
#include <onda.h>
#include <stdio.h>
int main(void) {
static const char source[] =
"params:\n"
" gain = 0.5\n"
"sample:\n"
" out1 = gain\n";
onda_compile_options_t options = {
.sample_rate = 48000.0f,
.block_size = 128,
};
onda_diag_t diag = {0};
onda_program_t* program = onda_compile(source, &options, &diag);
if (program == NULL) {
fprintf(stderr, "%s\n", diag.message ? diag.message : "compile failed");
onda_diag_dispose(&diag);
return 1;
}
onda_instance_t* instance =
onda_instance_create(program, NULL, &diag);
if (instance == NULL) {
fprintf(stderr, "%s\n", diag.message ? diag.message : "instance creation failed");
onda_program_destroy(program);
onda_diag_dispose(&diag);
return 1;
}
onda_configure_current_thread_audio_fp_mode();
if (onda_init_checked(instance, ONDA_INIT_FULL, NULL) != ONDA_EXECUTION_OK) {
onda_instance_destroy(instance);
onda_program_destroy(program);
onda_diag_dispose(&diag);
return 1;
}
float output[128];
int failed = onda_bind_output(instance, 0, output, (int)sizeof(output)) != 0 ||
onda_process_checked(instance, NULL) != ONDA_EXECUTION_OK;
if (failed) {
fprintf(stderr, "processing failed\n");
}
onda_instance_destroy(instance);
onda_program_destroy(program);
onda_diag_dispose(&diag);
return failed ? 1 : 0;
}
Create and initialize instances outside the audio callback. Bind every declared audio input and output before processing. An instance keeps its program alive, so you may release the original program handle after creating the instances you need.
Conventions
Handles and ownership
Opaque handles are reference-owning library objects:
| Handle | Created by | Released by |
|---|---|---|
onda_program_t |
A successful compile function | onda_program_destroy |
onda_instance_t |
An instance creation function | onda_instance_destroy |
onda_source_manifest_t |
Compilation through files or a source graph | onda_source_manifest_destroy |
onda_compile_constants_t |
A compile-constant inspection function | onda_compile_constants_destroy |
onda_project_image_t |
Capture, deserialize, or file loading | onda_project_image_destroy |
onda_project_materialization_plan_t |
onda_project_image_materialize |
onda_project_materialization_destroy |
Use *_destroy to release an opaque handle (NULL is allowed). Use *_dispose to release
Onda-owned members of a caller-allocated value, and *_reset to clear reusable counters without
freeing caller-owned storage.
Never pass an Onda-owned pointer to the C runtime free. Strings returned from program, manifest,
project-image, and descriptor queries are borrowed and remain valid until their owning handle is
destroyed. Occurrence payloads point into caller-owned batch storage and remain valid only until the
storage is modified or reused.
Programs are immutable and may be queried or used to create instances concurrently. An instance has one exclusive owner at a time: it may move between threads, but operations on the same instance must never overlap. Program and instance destruction are not realtime-safe.
Return values
| Result | Meaning |
|---|---|
NULL from a constructor |
Creation or compilation failed; inspect the diagnostic. |
0 from an operation |
Success. |
Negative ONDA_API_ERROR_* |
Argument, binding, lifecycle, or storage validation failed. |
Positive ONDA_EXECUTION_* |
Generated code rejected event input or failed during execution. |
-1 from a count, index, type, or size query |
Invalid input or an unavailable result. |
Borrowed-string queries return NULL for invalid input. Optional floating metadata uses NaN when
absent or invalid. Size-query functions return the required size without writing when the
destination is NULL or too small. Check the declaration in onda.h for a function’s exact result
convention.
Diagnostics
onda_diag_t carries a code, source span, message, optional file, and optional trace. Initialize it
to zero, dispose it before reusing it as an output, and dispose it when finished:
onda_diag_t diag = {0};
onda_program_t* program = onda_compile(source, &options, &diag);
if (program == NULL) {
fprintf(stderr, "%s\n", diag.message ? diag.message : "Onda compilation failed");
}
onda_diag_dispose(&diag);
Every non-NULL diagnostic string is Onda-owned. Copying onda_diag_t copies its pointers, not its
ownership; copied diagnostics must not be disposed independently.
Primitive and layout identifiers
The metadata and binding APIs use these primitive identifiers:
| Identifier | Native value representation |
|---|---|
ONDA_PRIMITIVE_F32 |
float |
ONDA_PRIMITIVE_F64 |
double |
ONDA_PRIMITIVE_I32 |
int32_t |
ONDA_PRIMITIVE_I64 |
int64_t |
ONDA_PRIMITIVE_BOOL |
uint8_t, exactly 0 or 1 |
Native parameter storage and parameter descriptor default_bytes use native byte order. Event and delegate
wire payloads contain no implicit alignment padding and use little-endian byte order. Fixed arrays
are contiguous; a top-level slice is encoded as a little-endian signed int32_t element count
followed by its packed field tensors.
Compilation
Compile options
All compilation and configuration-inspection entry points use onda_compile_options_t:
fast_math != 0permits floating-point arithmetic relaxations for faster processing.sample_ratemust be finite and positive.block_sizemust be positive.const_inputsisNULLwhenconst_input_countis zero.
The resulting program captures these values; instances do not choose another sample rate or block size later.
Source entry points
| Function | Input model |
|---|---|
onda_compile |
One NUL-terminated source string. |
onda_compile_file |
A filesystem .onda, .on, or .ondaproject entry. |
onda_compile_source_graph |
An exact in-memory graph of source documents and resolutions. |
onda_project_image_compile |
An immutable portable project image. |
onda_compile_file resolves imports, includes, project entries, and file-backed assets. Source and
asset paths must not traverse symbolic links. onda_compile_source_graph never consults the
filesystem: every non-standard-library reference must have one supplied
onda_source_graph_resolution_t.
onda_rewrite_source_references rewrites every parsed non-standard-library include/import in one
exact UTF-8 document. It returns the non-NUL output length and supports the ordinary two-call size
query pattern.
Compile-time configuration
Every source model has a matching configuration inspection function:
onda_inspect_compile_constantsonda_inspect_compile_constants_fileonda_inspect_compile_constants_source_graphonda_project_image_inspect_compile_constants
Omitted config const inputs use their authored defaults. Inspection resolves dependent values and
fixed-array lengths under the partial selection and returns immutable
onda_compile_const_descriptor_t values:
onda_compile_constants_t* constants =
onda_inspect_compile_constants_file("processor.onda", &options, NULL, &diag);
if (constants == NULL) {
/* Inspect diag and stop. */
}
int count = onda_compile_constants_count(constants);
for (int i = 0; i < count; ++i) {
const onda_compile_const_descriptor_t* descriptor =
onda_compile_constants_at(constants, i);
/* descriptor->input is a valid immutable compile input. */
}
options.const_inputs = onda_compile_constants_inputs(constants);
options.const_input_count = (size_t)count;
onda_program_t* program = onda_compile_file("processor.onda", &options, NULL, &diag);
onda_compile_constants_destroy(constants);
onda_compile_constants_inputs borrows one contiguous input array from the descriptor handle. The
handle must remain alive through the compile call. To override a value, supply native C storage:
float selected = 0.5f;
onda_compile_const_input_t input = {
.name_utf8 = "QUALITY",
.element_type = ONDA_PRIMITIVE_F32,
.is_array = 0,
.element_count = 1,
.values = &selected,
};
ONDA_COMPILE_CONST_KIND_SCALAR, ONDA_COMPILE_CONST_KIND_FIXED_ARRAY, and
ONDA_COMPILE_CONST_KIND_ARRAY distinguish the declaration shapes. Arrays use contiguous native
values and retain their resolved element count.
Source manifests
onda_compile_file, its inspection counterpart, and exact-source-graph entry points can return an
owned onda_source_manifest_t on success or failure. The manifest is suitable for dependency
watching, diagnostics, source capture, and replay.
| Query family | Functions |
|---|---|
| Contributing paths | onda_source_manifest_count, onda_source_manifest_path |
| Unresolved candidate paths | onda_source_manifest_unresolved_count, onda_source_manifest_unresolved_path |
| Filesystem watch set | onda_source_manifest_watch_count, onda_source_manifest_watch_path |
| Captured documents | onda_source_manifest_document_count, onda_source_manifest_document_info |
| Successful resolutions | onda_source_manifest_resolution_count, onda_source_manifest_resolution_info |
| Unresolved references | onda_source_manifest_unresolved_resolution_count, onda_source_manifest_unresolved_resolution_info, onda_source_manifest_unresolved_resolution_candidate_path |
| Cleanup | onda_source_manifest_destroy |
Resolution kinds are ONDA_SOURCE_REFERENCE_INCLUDE and ONDA_SOURCE_REFERENCE_IMPORT. Document
contents are exact byte slices and need not be NUL-terminated. Filesystem compilation returns
canonical absolute paths; source-graph compilation preserves opaque caller-supplied identities and
has an empty watch set.
Project images and buffer assets
Project images are immutable, filesystem-independent source graphs with canonical typed buffer assets. They are useful for portable storage, browser/native interchange, reproducible compilation, and later materialization into editable files.
Versions and canonical assets
onda_versionreturns a process-lifetime string containing the Onda release version.onda_project_image_format_versionreturns the supported project-image format version.onda_buffer_asset_format_versionreturns the canonical.ondabufferformat version.onda_current_stdlib_digestreturns a process-lifetime string identifying the embedded standard library.onda_buffer_asset_encodeencodes host-native primitive samples.onda_buffer_asset_decodevalidates an asset, reportsonda_buffer_asset_info_t, and optionally writes host-native samples.
The encode/decode functions return an int64_t required byte count or -1 on failure and support
size queries with a NULL or undersized destination.
Creating and serializing images
| Function | Purpose |
|---|---|
onda_project_image_capture |
Capture a successful source manifest below a source root and associate canonical assets. |
onda_project_image_load_files |
Load an editable project from a complete in-memory relative-file set. |
onda_project_image_with_buffer_overrides |
Return a new image with supplied buffer bindings replaced or added, retaining sources, constants, and unmentioned buffers. |
onda_project_image_deserialize |
Validate and own a serialized canonical image. |
onda_project_image_serialize |
Serialize an image with a two-call size query. |
onda_project_image_content_digest |
Borrow the canonical content digest. |
onda_project_image_destroy |
Destroy the image. |
onda_project_image_load_files accepts .ondabuffer, WAV, and inline project buffers. If the file
set contains multiple .ondaproject files, select one explicitly; otherwise pass NULL and require
an unambiguous project.
onda_project_image_with_buffer_overrides takes canonical onda_project_buffer_asset_t
assets and leaves the input image unchanged, including on failure. Duplicate
names and invalid assets are rejected. Unreferenced assets are discarded, and
declaration compatibility is checked when compiling the resulting image. Pass
NULL with a zero count to obtain an independently owned copy.
Inspecting and compiling images
| Data | Functions |
|---|---|
| Entry and standard-library identity | onda_project_image_entry, onda_project_image_stdlib_digest |
| Documents | onda_project_image_document_count, onda_project_image_document_info |
| Resolutions | onda_project_image_resolution_count, onda_project_image_resolution_info |
| Logical buffers | onda_project_image_buffer_count, onda_project_image_buffer_info |
| Configuration and compilation | onda_project_image_inspect_compile_constants, onda_project_image_compile |
Programs compiled from project files or images retain immutable decoded buffer defaults. Instances use them automatically until the host rebinds or explicitly unbinds the corresponding slot. Compilation rejects a project-bound asset when reachable Onda code may write it.
Materializing editable files
onda_project_image_materialize returns an owned plan. Inspect it with
onda_project_materialization_file_count, onda_project_materialization_file_info, then release it with
onda_project_materialization_destroy. The record borrows file bytes until plan destruction.
Program metadata
All metadata belongs to the immutable onda_program_t. Returned strings and pointers remain valid
until onda_program_destroy. Indices are stable for the program’s lifetime.
Borrowed descriptors
Counts and name-to-index lookups remain available. A single descriptor query returns each surface’s immutable metadata; a null pointer means an invalid program or index.
| Surface | Descriptor query | Record |
|---|---|---|
| Input | onda_input_info |
onda_value_info_t |
| Output | onda_output_info |
onda_value_info_t |
| Control output | onda_control_output_info |
onda_value_info_t |
| Parameter | onda_param_info |
onda_value_info_t |
| State | onda_state_info |
onda_value_info_t |
| Buffer | onda_buffer_info |
onda_buffer_info_t |
| Buffer array | onda_buffer_array_info |
onda_buffer_array_info_t |
| Event | onda_event_info |
onda_message_info_t |
| Delegate | onda_delegate_info |
onda_message_info_t |
Value records contain names, type text, primitive element type, array shape, slot and byte offsets,
exact native default bytes, numeric defaults/ranges, control scale, curve, step, unit and enum JSON.
Optional strings and default bytes are null when absent; optional numeric fields use their
has_* flags and NaN where appropriate. slot_offset is -1 for state. Enum JSON is borrowed until
program destruction. Its shape is
{"name":"Mode","members":[{"name":"LowPass","label":"Low Pass"},...]}; member ordinals
use i32 storage. onda_state_total_bytes reports the persistent snapshot size.
Buffer records describe primitive width, channel constraints and whether reachable code may write
the buffer. Buffer-array records identify a contiguous run of physical slots by first and len.
onda_param_normalized_to_plain and onda_param_plain_to_normalized implement control-domain
conversion. Numeric arrays share their element domain. Booleans use the value >= 0.5 threshold;
unranged numeric conversions return NaN. Raw parameter bytes retain full-width i64 values;
double control values are exact only through ONDA_MAX_EXACT_HOST_CONTROL_INTEGER.
Messages and tensor views
Message records contain a recursive schema_json, fixed/minimum packed payload sizes, delegate
record sizes, tensor/region counts and an immutable borrowed payload_plan. Fixed sizes are -1 for dynamic messages; event record sizes are -1.
The schema preserves nested structs, tuples, arrays, slices, exact defaults and enum/integer domains.
onda_payload_tensor_info(plan, index) returns a borrowed descriptor for either an event or
delegate leaf, or null for an invalid plan/index. It exposes each leaf in dispatch order: path, owning
parameter, primitive type, fixed shape, element product and dynamic outer-slice marker. For fixed
parameters, fixed_element_count is the view’s element count; for slices, multiply it by the
logical slice length. Paths and shapes are borrowed until program destruction.
onda_payload_layout resolves either an event or delegate plan from one nonnegative logical length
per top-level slice, in declaration order. It returns packed payload bytes, aligned preparation
workspace bytes, and the number of regions. Pass NULL, 0 for the region storage to query only
those totals; otherwise supply caller-owned storage for every region. The query allocates nothing
and checks all lengths, overflow and capacity before writing any output. Failures leave both the
summary and region array unchanged and return the corresponding ONDA_API_ERROR_* status.
onda_payload_layout_from_bytes resolves the same regions from a complete packed payload,
reading slice-length prefixes without decoding or normalizing scalar values. It accepts both event
and delegate plans and uses the same storage, sizing, allocation-free and failure-atomic contracts.
Truncated/trailing bytes or negative lengths return ONDA_API_ERROR_INVALID_SHAPE. This is suitable
for host decoders and inspectors; it does not validate primitive values or execute a handler.
Regions appear in wire order, with one region per primitive tensor and one additional region per
slice length prefix. parameter_index identifies the source parameter; tensor_index is the
flattened leaf index or -1 for a length prefix. Each region reports its element count, packed byte
offset/size and aligned workspace offset. Empty tensors retain zero-byte regions, so region count
depends on schema shape, not array capacity or slice length. Offsets exclude delegate record headers.
For example, gain: f32, points: f32[], enabled: bool with three points has four regions at
offsets 0, 4, 8 and 20, and a 21-byte payload:
const onda_message_info_t* event = onda_event_info(program, event_index);
int32_t lengths[] = { 3 };
onda_payload_region_t regions[4];
onda_payload_layout_t layout;
int status = onda_payload_layout(event->payload_plan, lengths, 1,
regions, 4, &layout);
The plan is borrowed until program destruction and needs no separate destroy call. Queries may
run concurrently with separate output storage. Reserve layout.workspace_bytes with
onda_instance_reserve_event_workspace before realtime dispatch when necessary. Layout resolution
does not encode values, normalize domains, or dispatch events. Native tensor views remain available
for synchronous calls that do not need packed transport.
Print source metadata
onda_source_file_count and onda_source_file_path expose the artifact-local source table.
onda_log_site_count and onda_log_site_info expose each concrete print site’s label, source span,
lexical owner, declaration, primitive argument types, and fixed payload size. All pointers in
onda_log_site_info_t are borrowed from the program.
Instance lifecycle
Creation
onda_instance_create(program, allocator, out_diag) allocates program-shaped storage, installs
parameter and project-buffer defaults, and returns an uninitialized instance. Pass NULL for the
default allocator. Sample rate, block size and channel counts come from the compiled program.
Call onda_init_checked explicitly and inspect its execution status. Release the instance with
onda_instance_destroy.
Hosts own floating-point thread policy. onda_configure_current_thread_audio_fp_mode() optionally
enables the audio policy on the calling thread (FTZ/DAZ on x86, FZ on ARM64). Every explicit call reapplies it.
Call it before initialization, events or processing on each execution thread when desired; hosts
that share a thread with other work own saving/restoring the prior mode. Runtime calls never change
this policy implicitly.
onda_allocator_t affects only instance-owned runtime storage. Its alloc callback runs
synchronously during creation and explicit onda_instance_reserve_event_workspace calls. Realtime
dispatch does not allocate. free may run during failed creation, reservation, or destruction.
The context and callbacks must remain valid until every associated
instance is destroyed and must support the threads/concurrency used by the host.
Use onda_instance_reserve_event_workspace(instance, capacity_bytes, out_diag) outside the audio
callback when dynamic event payloads need more preparation storage. Fixed messages fit the initial
capacity; dynamic messages initially have at least 64 KiB. Reservation can run before or after
initialization. Failure preserves the existing workspace and processor state; dispatch rejects an
oversized event without invalidating the instance.
Initialization
onda_init_checked(instance, mode, output) reruns authored initialization in place:
ONDA_INIT_FULLinitializes the complete state and is required before processing a newly created uninitialized instance.ONDA_INIT_PRESERVE_PINNEDreinitializes ordinary state while preserving pinned state and task continuations. It is valid only after successful full initialization.
Initialization observes the instance’s current external-buffer bindings. Project
defaults are installed during creation before explicit initialization; ordinary
unbound slots use their neutral descriptors. Rebinding does not rerun initialization automatically;
call onda_init_checked when state derived by an earlier initializer should be recomputed from the
new binding.
The successful path allocates nothing. Checked initialization returns an ONDA_API_ERROR_* code
when validation rejects the request before generated code runs. It returns
ONDA_EXECUTION_RUNTIME_SAFETY_FAILURE when generated initialization fails; that failure leaves
state indeterminate, and the instance rejects stateful operations until a full initialization or
snapshot restore succeeds.
Initialization, processing, events, binding validation, and snapshot operations do not allocate error strings. They report numeric statuses; format diagnostics outside the audio callback.
Print records emitted before a generated failure remain available; delegate records are cleared. Validation rejection preserves state. Full initialization or successful restore recovers invalidated state; preserve-pinned initialization requires initialized state.
Parameters and bindings
Parameter writes
onda_set_param_by_indexwrites an exact scalar or fixed-array value from native packed bytes.onda_set_param_element_by_indexwrites one primitive scalar or fixed-array element from native bytes without modifying its siblings.onda_set_param_plain_f64constrains a scalar plain value to its range and step.onda_set_param_element_plain_f64applies the same conversion to one scalar or fixed-array element.onda_set_param_normalizedconverts a normalized[0, 1]scalar host value into the declared plain domain.onda_set_param_element_normalizedapplies the same conversion to one scalar or fixed-array element.
Use raw bytes for full-width i64 parameters and whole-array writes.
Audio bindings
onda_bind_input and onda_bind_output install zero-copy host memory for one declared entry. The
pointer must be naturally aligned, correctly sized for the program’s compile-time block size, and
stable until the entry is rebound, unbound with NULL plus zero bytes, or the instance is destroyed.
Generated code accesses the memory directly.
Bound input, output, and buffer regions must not overlap. Checked processing validates required bindings before execution.
External buffers
onda_bind_buffer installs one zero-copy physical buffer slot using a primitive type, positive
frames/channels, and sample rate. A replacement binding is used by subsequent init, event, and
processing calls without reconstructing the instance. The memory must be writable when
the buffer descriptor’s may_write field is true.
Either of these forms unbinds a buffer:
sample_rate == 0, regardless of pointer and shape.ptr == NULL,frames == 0, andchannels == 0.
An unbound buffer remains processable through neutral one-frame storage: reads return zero and
writes are discarded. onda_reset_buffer_to_project_default restores an immutable default retained
from a compiled project.
Process readiness
Binding calls validate shape, extent, type, and alignment. A rejected bind preserves the previous binding. Host memory must remain valid until it is rebound, unbound, or the instance is destroyed.
onda_prepare_process checks initialization and required audio bindings before using unchecked
processing. Successful rebinds preserve readiness. Unbinding required audio or an execution failure
revokes it.
Processing
Checked processing
onda_process_checked(instance, output) processes exactly the compiled block size, running both
beginning- and end-of-block work. Use the segment API for a shorter prefix or offset.
onda_process_checked_segment(instance, start_frame, frames, flags, output) splits one logical
block while keeping full-block bindings:
- The first segment includes
ONDA_PROCESS_BEGIN_BLOCK. - The final segment includes
ONDA_PROCESS_END_BLOCK. - An unsplit block uses
start_frame = 0andONDA_PROCESS_FULL_BLOCK.
Generated local frame i accesses host frame start_frame + i.
Both checked processing functions return an ONDA_API_ERROR_* code when request or binding
validation fails before execution. They return ONDA_EXECUTION_RUNTIME_SAFETY_FAILURE when
generated code fails; that failure invalidates processor state until successful full initialization
or snapshot restoration.
Unchecked processing
After successful onda_prepare_process, use onda_process_unchecked for one complete compiled
block or onda_process_unchecked_segment for segmented processing. The instance must remain
initialized with complete, valid bindings.
Unchecked calls avoid repeated host-boundary validation but do not suppress generated runtime safety
checks. ONDA_EXECUTION_OK is success;
ONDA_EXECUTION_RUNTIME_SAFETY_FAILURE indicates a generated failure. A runtime failure invalidates
state until successful full initialization or snapshot restoration.
Events
onda_trigger_event_by_index_checked validates readiness and packed payload data before running
a top-level event. It returns ONDA_EXECUTION_INPUT_REJECTED for malformed input or
insufficient workspace and ONDA_EXECUTION_RUNTIME_SAFETY_FAILURE for handler failure. Unknown
event indices return success without running a handler.
onda_trigger_event_by_index_unchecked requires successful full initialization and a payload plus
buffer state satisfying the ABI contract. Like unchecked processing, it may return a positive
generated failure code or an ONDA_API_ERROR_* code.
onda_trigger_event_views_by_index_checked is the native zero-copy alternative. It accepts one
onda_event_tensor_view_t per primitive schema leaf, in declaration and depth-first field order.
element_count is the number of primitive scalars in that leaf; leaves belonging to the same
top-level slice must therefore imply the same logical length after their fixed inner array extents
are removed. Every leaf is one contiguous, naturally aligned native-endian tensor. Struct slices
therefore use structure-of-arrays storage: one view for each primitive field, rather than strided
views into an array-of-structs allocation.
The checked view call verifies tensor count, shapes, shared lengths, alignment, pointer arithmetic, and canonical bool and ranged-integer values before executing. Unlike packed wire input, borrowed views represent logical native values, so noncanonical values are rejected rather than normalized. It borrows the supplied tensors without packing or copying their contents. Nonempty regions must remain readable and unchanged until the synchronous call returns and must not overlap memory written by the event. Empty views may use a null data pointer. As with all C pointer APIs, the caller owns the validity of the described allocations.
onda_trigger_event_views_by_index_unchecked uses exactly the same canonical SoA representation,
but derives the tensor count from the event schema and performs no instance, buffer, tensor shape,
alignment, or value validation. The instance must be fully initialized with prepared buffer
bindings established by successful binding calls, and
tensors must point to the exact schema-derived number of valid views. Violating this contract is
undefined behavior. This is the minimum-overhead entry for hosts that prepare and reuse known-correct
views.
All event functions accept an optional execution output and execute synchronously on the calling thread.
Event payloads use the recursive schema returned by onda_event_info(...)->schema_json. Encode parameters in
declaration order and fields depth-first; structs are structure-of-arrays tensors, and each dynamic
slice contributes one little-endian i32 logical length followed by its leaf tensors. Use
onda_payload_layout to resolve dynamic wire regions and preparation workspace, reserve additional
workspace before realtime dispatch when necessary, and treat input rejection separately from
handler failure. The processor remains usable after rejected input.
Delegates
For collection examples across C, Rust, and raw objects, see the host output guide.
Top-level delegates are sparse typed output occurrences. Proc-local routing and when handlers run
synchronously inside generated code; optional host collection copies top-level occurrences into a
caller-owned onda_delegate_batch_t.
Use the batch cursor helpers to read records. Each occurrence identifies its delegate, payload,
and call-local sequence. The message descriptor reports exact fixed payload and record sizes, or
minimum sizes for dynamic messages. Choose a batch capacity for your application and monitor
overflow_count: the number and size of occurrences can depend on runtime input.
uint8_t delegate_storage[64 * 1024];
onda_delegate_batch_t delegates = {
.storage = delegate_storage,
.capacity_bytes = sizeof(delegate_storage),
};
onda_execution_output_t output = {
.delegate_batch = &delegates,
.print_batch = NULL,
};
int status = onda_process_checked(instance, &output);
if (status == ONDA_EXECUTION_OK) {
onda_batch_cursor_t cursor = {0};
onda_delegate_occurrence_t occurrence;
int next;
while ((next = onda_delegate_batch_next(&delegates, &cursor, &occurrence)) > 0) {
/* Decode occurrence.payload using occurrence.delegate_index metadata. */
}
if (next < 0) handle_malformed_batch();
}
Each supplied delegate or print batch descriptor and its non-null storage must be disjoint from the other batch and from every region accessed during the call, including bound input, output, and buffer storage plus packed event payloads or native event tensor views. This non-overlap requirement also applies to checked entry points.
onda_delegate_batch_reset clears counters without changing storage. The runtime host resets every
supplied batch before init or process code; an event entry resets it before input preflight, so
rejected events return empty batches.
onda_delegate_batch_next performs linear constant-time cursor iteration, returning 1 for a
record, 0 at the end, and -1 for invalid or malformed input.
Use the cursor API for linear iteration; consume it through the end to validate the complete batch.
Missing storage suppresses only the host copy. Calls and internal handlers still run. Records are
appended whole; insufficient capacity drops the record and increments saturated overflow_count.
Successful generated execution leaves the batch for the host to consume before reuse. Generated
failure clears delegate results.
Printing
Collect authored print(...) output in a caller-owned onda_print_batch_t. Use
onda_format_print_batch to obtain displayable text, or iterate typed records with
onda_print_batch_next. If you combine prints and delegates in one log, merge their records by
sequence within each call.
uint8_t print_storage[64 * 1024];
onda_print_batch_t prints = {
.storage = print_storage,
.capacity_bytes = sizeof(print_storage),
};
onda_execution_output_t output = {
.delegate_batch = NULL,
.print_batch = &prints,
};
int status = onda_process_checked(instance, &output);
onda_owned_string_t text = {0};
onda_diag_t diag = {0};
if (onda_format_print_batch(instance, &prints, &text, &diag) == 0) {
fwrite(text.data, 1, text.length, stdout);
}
onda_owned_string_dispose(&text);
onda_diag_dispose(&diag);
onda_print_batch_reset and onda_print_batch_next parallel the
delegate helpers, including their result conventions. The occurrence site index resolves through
onda_log_site_info.
onda_format_print_batch allocates one Onda-owned NUL-terminated string. Its output must be empty on
entry and must later be released with onda_owned_string_dispose. onda_format_print_batch_into
formats into caller-owned memory without allocation: out_length receives the required non-NUL
length, the destination is untouched unless it can hold the complete text plus a trailing NUL, and
the destination must not overlap batch storage. Both return ONDA_API_ERROR_INVALID_ARGUMENT for
required null inputs and ONDA_API_ERROR_VALIDATION_FAILED for malformed batch contents.
Print and delegate storage are independently nullable and never share capacity. Omitting print
storage suppresses delivery without suppressing argument evaluation. Overflow drops complete
records and increments overflow_count. Unlike delegates, print records emitted before a generated
failure remain available for diagnostics.
State snapshots and control outputs
onda_state_total_bytes(program) reports the packed persistent-state snapshot size.
onda_instance_snapshot_state copies persistent state, excluding scratch and control-output
mirrors. A NULL or undersized destination performs a size query. Invalid arguments return -1;
a requested copy returns ONDA_API_ERROR_UNINITIALIZED or ONDA_API_ERROR_INVALIDATED when state is unavailable.
onda_instance_restore_state runs full initialization and then overlays an exact snapshot. Invalid
snapshot or binding input is rejected with an ONDA_API_ERROR_* code before execution and preserves
the prior state. A generated initializer failure returns ONDA_EXECUTION_RUNTIME_SAFETY_FAILURE
and leaves state indeterminate. The internal initialization is silent: restore does not collect or
publish its print output.
onda_control_output_read_bytes copies the latest held value of one top-level kouts entry and
uses the same size-query convention.
Function index
See onda.h for complete signatures and structure definitions.
All C API functions
onda_bind_buffer
onda_bind_input
onda_bind_output
onda_buffer_array_count
onda_buffer_array_info
onda_buffer_asset_decode
onda_buffer_asset_encode
onda_buffer_asset_format_version
onda_buffer_count
onda_buffer_index
onda_buffer_info
onda_compile
onda_compile_constants_at
onda_compile_constants_count
onda_compile_constants_destroy
onda_compile_constants_inputs
onda_compile_file
onda_compile_source_graph
onda_configure_current_thread_audio_fp_mode
onda_control_output_count
onda_control_output_index
onda_control_output_info
onda_control_output_read_bytes
onda_current_stdlib_digest
onda_delegate_batch_next
onda_delegate_batch_reset
onda_delegate_count
onda_delegate_index
onda_delegate_info
onda_diag_dispose
onda_event_count
onda_event_index
onda_event_info
onda_payload_tensor_info
onda_format_print_batch
onda_format_print_batch_into
onda_init_checked
onda_input_count
onda_input_index
onda_input_info
onda_inspect_compile_constants
onda_inspect_compile_constants_file
onda_inspect_compile_constants_source_graph
onda_instance_create
onda_instance_destroy
onda_instance_reserve_event_workspace
onda_instance_restore_state
onda_instance_snapshot_state
onda_log_site_count
onda_log_site_info
onda_output_count
onda_output_index
onda_output_info
onda_owned_string_dispose
onda_param_count
onda_param_index
onda_param_info
onda_param_normalized_to_plain
onda_param_plain_to_normalized
onda_payload_layout
onda_payload_layout_from_bytes
onda_prepare_process
onda_print_batch_next
onda_print_batch_reset
onda_process_checked
onda_process_checked_segment
onda_process_unchecked
onda_process_unchecked_segment
onda_program_destroy
onda_project_image_buffer_count
onda_project_image_buffer_info
onda_project_image_capture
onda_project_image_compile
onda_project_image_content_digest
onda_project_image_deserialize
onda_project_image_destroy
onda_project_image_document_count
onda_project_image_document_info
onda_project_image_entry
onda_project_image_format_version
onda_project_image_inspect_compile_constants
onda_project_image_load_files
onda_project_image_materialize
onda_project_image_resolution_count
onda_project_image_resolution_info
onda_project_image_serialize
onda_project_image_stdlib_digest
onda_project_image_with_buffer_overrides
onda_project_materialization_destroy
onda_project_materialization_file_count
onda_project_materialization_file_info
onda_reset_buffer_to_project_default
onda_rewrite_source_references
onda_set_param_by_index
onda_set_param_element_by_index
onda_set_param_element_normalized
onda_set_param_element_plain_f64
onda_set_param_normalized
onda_set_param_plain_f64
onda_source_file_count
onda_source_file_path
onda_source_manifest_count
onda_source_manifest_destroy
onda_source_manifest_document_count
onda_source_manifest_document_info
onda_source_manifest_path
onda_source_manifest_resolution_count
onda_source_manifest_resolution_info
onda_source_manifest_unresolved_count
onda_source_manifest_unresolved_path
onda_source_manifest_unresolved_resolution_candidate_path
onda_source_manifest_unresolved_resolution_count
onda_source_manifest_unresolved_resolution_info
onda_source_manifest_watch_count
onda_source_manifest_watch_path
onda_state_count
onda_state_info
onda_state_total_bytes
onda_trigger_event_by_index_checked
onda_trigger_event_by_index_unchecked
onda_trigger_event_views_by_index_checked
onda_trigger_event_views_by_index_unchecked
onda_version