C++ Node API Reference

Basic types

Number

Represents a XOD number. In current implementations typedef’ed to IEEE 754 32-bit floating point data type.

TimeMs

Represents a big integer to store time values expressed in milliseconds. Typedef’ed to 32-bit unsigned integer.

XString

Represents XOD string. Typedef’ed to List<char>, so the same methods and functions may be used to manipulate it.

Context

An opaque type to distinguish a particular instance of node among other nodes of the same type.

Required as an argument for most node functions. Can be thought as an explicit this in many OOP languages, or like the self in Python.

State

A user-defined struct to store node’s data for a lifetime of the program. Each node type has its own State definition.

input_$$$

Automatically generated descriptor for each of node’s inputs. Never instantiated. Used as a template argument in functions to access input data.

$$$ gets replaced by a pin label as is. For example, input_FOO, input_Smin. If a node has a single unlabeled input, input_IN is generated for it. If a node has multiple unlabeled inputs, they are referred as input_IN1, input_IN2,…, input_IN7.

output_$$$

Automatically generated descriptor for each of node’s outputs. Never instantiated. Used as a template argument in functions to access output data.

$$$ gets replaced by a pin label as is. For example, output_BAR, output_Tc. If a node has a single unlabeled output, output_OUT is generated for it. If a node has multiple unlabeled outputs, they are referred as output_OUT1, output_OUT2,…, output_OUT7.

XOD runtime supports no more than seven outputs on C++ nodes.

Node functions

void evaluate(Context ctx)

Entry-point function for any C++ node. Called by the runtime when a node requires re-evaluation for whatever reason: input data update, schedule timeout, etc. Each C++ node must implement evaluate.

ValueT getValue<input_$$$|output_$$$>(Context ctx)

Returns the most recent value on an input or output pin. The result type ValueT depends on pin data type and could be bool, Number, etc.

Note, the pulse type has no values. It’s meaningless to call getValue on a pulse-type pin. To know if a pulse was fired use isInputDirty instead.

A node owns its output values, so in simple cases, they could serve both as values for downstream nodes and as node’s state storage. In such cases use getValue<output_$$$>(ctx) to access the last emitted output value.

void emitValue<output_$$$>(Context ctx, ValueT value)

Sets new value on an output pin. The argument type ValueT depends on pin data type and can be bool, Number, etc.

A call to emitValue causes immediate downstream nodes to be re-evaluated within the current transaction even if the output value has not changed. If it’s cheap to check, avoid sending duplicate values.

To emit a pulse, use true as the value.

bool isInputDirty<input_$$$>(Context ctx)

Returns true if and only if the input pin specified has got a newly emitted value during the current transaction.

State* getState(Context ctx)

Returns a pointer to the persistent state storage for the current node. The State structure is defined by the node author. Fields could be updated directly, with the pointer returned, no commit is required after a change.

bool isSettingUp()

Returns true if the evaluation takes place inside the very first transaction. Use the function to run some initialization code once on boot, or prevent undesirable initial values emission.

TimeMs transactionTime()

Returns time of the current transaction since the program started, in milliseconds. Stays constant for the whole duration of any particular transaction. Prefer this function to millis to avoid time difference error accumulation.

void setTimeout(Context ctx, TimeMs timeout)

Schedules a forced re-evaluation of a node past timeout milliseconds after the current transaction time.

A node may have at most one scheduled update. If called multiple times, the subsequent calls cancel the previous schedule for the node.

Pass 0 for timeout to schedule evaluation right after the current transaction completes. Effectively it forces a new transaction trigger after the current.

void clearTimeout(Context ctx)

Cancels scheduled evaluation of a node (if present). Safe to call even if the update was not scheduled.

bool isTimedOut(Context ctx)

Returns true if node’s schedule timed out right at the current transaction. Unless scheduled again will return false since the next transaction.

List objects

Lists in XOD are not classical linked lists, nor vectors. They are smart (or dumb) views over existing data. The only useful thing a list can do is to create an Iterator<T> allowing to enumerate list values from the head to the tail.

Usage example

Number sum(List<Number> numbers) {
    Number result = 0;
    for (Iterator<Number> it = numbers.iterate(); it; ++it)
        result += *it;
    return result;
}

List<T>

A list of elements of type T.

A List<T> is a thin Pimpl-wrapper around a ListView<T>. Since internally a List<T> contains just a single pointer passing a list by value is a cheap operation.

List<T>::List()

Constructs a new nil (null element) list.

List<T>::List(const ListView<T>* view)

Wraps a view into a list. The view must be kept alive for the whole list lifetime. Otherwise, the program will crash. This requirement is not checked automatically.

Iterator<T> List<T>::iterate() const

Creates a new iterator pointing to the first element of the list.

Iterator<T>

An iterator of List<T>. Iterators are expected to be short-living objects to enumerate elements of a list. They should not be cloned or passed around. An iterator points either to a valid element or it points out of list bounds. The later is used to denote iteration completed.

Iterator<T>::operator bool() const

Implicit cast to bool type. Returns true if the iterator points to a valid element, i.e. if the iterator is valid.

T Iterator<T>::operator*() const

Returns the element pointed by the iterator. Mimics pointer dereference. Returns a default value for type T if the iterator is not valid.

bool Iterator<T>::value(T* out) const

Checks validity and retrieves element at once. Returns true if the iterator is valid, writes the element into out in that case. If the iterator is invalid returns false and keeps out intact.

Iterator& Iterator<T>::operator++()

Advances the iterator to the next element. May make it invalid. Conventionally returns self.

List functions

size_t length(List<T> xs)

Returns a length of the list. To compute it iterates over all elements, so it’s not a trivial operation, so prefer caching the result over calling length multiple times.

size_t dump(List<T> xs, T* outBuff)

Copies elements from list xs into the flat outBuff. A caller must guarantee that the buffer pointed has enough size to contain all elements of the list. Otherwise, the program will crash.

TR foldl(List<T> xs, TR (*func)(TR, T), TR acc)

Performs left fold (also known as “reduce”) of the list xs using func reducer function and acc as starting value for the accumulator.

Found a typo or mistake? Want to improve the text? Edit this page on GitHub and open a pull request. If you have a complex proposal or you want to discuss the content, feel free to start a new thread on XOD forum.