12.6.9 Views

The cpp.marshal.View type is a built-in stack-only value type extern which can be used to represent a contiguous region of memory, managed or unmanaged. It provides a convenient API for working with memory with zero GC allocations due to being a stack only type, all while guaranteeing safe access and performance near to raw pointer use.

Convenience functions for creating views from standard Haxe types exist in the cpp.marshal.ViewExtensions class. E.g. you can create a span from a haxe.ds.Vector.

import cpp.marshal.View;
import haxe.ds.Vector;

using cpp.marshal.ViewExtensions;
using haxe.Int64;

function main() {
    final source = new Vector<Int>(10);
    final view   = source.asView();

    for (i in 0...view.length.toInt()) {
        view[i] = i;
    }

    trace(source); // [ 0, 1, 2, 3, 4, 5, 6, 7, 8, 9 ]
}

The same sample can also work over native memory with minimal changes.

import cpp.marshal.View;

using cpp.marshal.ViewExtensions;
using haxe.Int64;

function main() {
    final source : cpp.Star<cpp.UInt8> = Native.malloc(10);
    final view   = Pointer.fromStar(source).asView(10);

    for (i in 0...view.length.toInt()) {
        view[i] = i;
    }

    trace(view.toArray()); // [ 0, 1, 2, 3, 4, 5, 6, 7, 8, 9 ]
}

Slices

The two slice overloads return a new view pointing to a sub-region of the original view. These functions provide an ergonomic way of working with regions of memory without extra allocations or needing to manually managed indexes and lengths.

import cpp.marshal.View;
import haxe.ds.Vector;

using cpp.marshal.ViewExtensions;
using haxe.Int64;

function main() {
    final source = new Vector<Int>(10);
    final view   = source.asView().slice(2, 5);

    for (i in 0...view.length.toInt()) {
        view[i] = 10 + i;
    }

    trace(source); // [ 0, 0, 10, 11, 12, 13, 14, 0, 0, 0 ]
}

Reinterpret

By reinterpreting a view you can treat the region of memory as another type, including value type externs. The following sample allocates bytes, reinterprets them as the Point value type extern, and writes random values to their x and y fields. Because cpp.marhal.View points to a region of memory all these writes occur on the original haxe.io.Bytes object.

import cpp.marshal.View;
import haxe.ds.Vector;

using cpp.marshal.ViewExtensions;
using haxe.Int64;

function main() {
    final source = new Vector<Int>(10);
    final view   = source.asView().slice(2, 5);

    for (i in 0...view.length.toInt()) {
        view[i] = 10 + i;
    }

    trace(source); // [ 0, 0, 10, 11, 12, 13, 14, 0, 0, 0 ]
}