This page has no translation to 한국어 yet. The original English version is below. If you’d like to help, great! See how to translate a documentation page in the contribution guide.

Migrating C++ Implementations to v0.35 Syntax

Before 0.35, C++ implementations of XOD nodes looked like this:

// a special marker to put code in the global scope
{{#global}}
#include <SPI.h>
#include <SD.h>
{{/global}}

// A struct to keep node state.
// Must be declared even if the node is stateless.
struct State {
    Number foo;
};

// a special marker between `State` and `evaluate`
{{ GENERATED_CODE }}

void evaluate(Context ctx) {
    auto state = getState(ctx); // accessing state struct
    state->foo++; // manipulating state
    // ...
}

In XOD v0.35, we introduced new implementation syntax that feels more like native C++ and gets rid of a few quirks.

Note

Implementations with old syntax will continue to work.

Let’s take a look at a few cases.

Stateless nodes #

Before 0.35:

// `State` struct must be declared even if it's not used
struct State {};

{{ GENERATED_CODE }}

void evaluate(Context ctx) {
    // ...
}

After:

// no separate `State` struct

// no `GENERATED_CODE` marker

node {
    void evaluate(Context ctx) {
        // ...
    }
}

Nodes with state #

Before:

struct State {
    Number foo;
};

{{ GENERATED_CODE }}

void evaluate(Context ctx) {
    auto state = getState(ctx); // accessing state struct
    state->foo++; // manipulating state
    // ...
}

After:

node {
    // just like fields in a regular C++ struct
    Number foo;

    void evaluate(Context ctx) {
        // no more `getState`
        foo++; // use the fields directly
        // ...
    }
}

Global scope and including libraries #

Before:

// all code in the implementation was inside node namespace by default

// a special marker to put code in the global scope
{{#global}}
#include <SPI.h>
#include <SD.h>
{{/global}}

struct State {};

{{ GENERATED_CODE }}

void evaluate(Context ctx) {
  // ...
}

After:

// everything outside `node` is global by default,
// no special markers needed
#include <SPI.h>
#include <SD.h>

// explicitly put something in node namespace
nodespace {
    static const unsigned char bitmap[] PROGMEM = {/* ... */};
}

node {
    Foo foo = Foo(bitmap);

    void evaluate(Context ctx) {
        // ...
    }
}

Accessing pin types #

Before:

struct State {
    // `ValueType<output_OUT>::T` was not available
    // before GENERATED_CODE marker
    // and could not be used to declare state
};

{{ GENERATED_CODE }}

void evaluate(Context ctx) {
   ValueType<output_OUT>::T foo = {};
  // ...
}

After:

node {
    // much simpler syntax,
    // available everywhere inside `node` struct
    typeof_IN previous = {};

    void evaluate(Context ctx) {
        typeof_OUT foo = {};
        // ...
    }
}

Defining custom types #

Before:

struct State {};

using Type = XColor;

{{ GENERATED_CODE }}

void evaluate(Context ctx) {
    Type color = getValue<output_OUT>(ctx);
    emitValue<output_OUT>(ctx, color);
}

After:

node {
    // Type definition is moved inside `node` and is wrapped in `meta`
    meta {
        using Type = XColor;
    }

    void evaluate(Context ctx) {
        Type color = getValue<output_OUT>(ctx);
        emitValue<output_OUT>(ctx, color);
    }
}
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.