Getting Started in C#
The C API is the primary public surface of ovstage. The fastest way to get running is the minimal C/C++ example: it interns paths through the path dictionary, creates an ovstage instance, writes an attribute column, advances the write floor, and reads the latest committed data back.
Building the Minimal Example#
The example builds standalone with CMake. On first configure it locates an ovstage package
using find_package(ovstage) and otherwise fetches the released package (refer to
examples/c/cmake/ovstage.cmake).
cd examples/c/minimal
# Linux
cmake -B build -DCMAKE_BUILD_TYPE=Release
cmake --build build
./build/minimal
On Windows, configure and build the same way (cmake -B build, then cmake --build
build --config Release) and put the ovstage package bin/ directory on PATH before
running; on Linux the build sets an rpath onto the package bin/ so the binary runs with
no environment setup. Refer to examples/c/minimal/README.md for details.
Expected output:
attribute token <N> = 'temperature'
read back ordinal 1: 1.0 2.0 3.0
The source for this example lives at examples/c/minimal/main.cpp in the public ovstage
tree.
Minimal Example#
// Write one float per prim into the "temperature" column (UPSERT creates
// the prims on first write), seal it by advancing the write floor to
// ordinal 1, then read the column back.
float values[] = { 1.0f, 2.0f, 3.0f };
int64_t shape[] = { 3 };
int64_t strides[] = { 1 };
DLTensor tensor{};
tensor.data = values;
tensor.device = { kDLCPU, 0 };
tensor.ndim = 1;
tensor.dtype = { kDLFloat, 32, 1 }; // {code, bits, lanes}
tensor.shape = shape;
tensor.strides = strides;
ovstage_write_data_t write{};
write.tensors = &tensor;
write.tensor_count = 1;
write.is_array = false;
ovstage_enqueue_result_t enq =
ovstage_write_attribute(stage, query, attrArg, /*ordinal*/ 1, write, OVSTAGE_PRIM_MODE_UPSERT);
waitOp(stage, enq, "write_attribute");
ovstage_write_floor_desc_t writeFloor{};
writeFloor.ordinal = 1;
writeFloor.scope = OVSTAGE_SCOPE_ALL;
enq = ovstage_advance_write_floor(stage, &writeFloor);
waitOp(stage, enq, "advance_write_floor");
ovstage_ordinal_range_t range{};
range.end_ordinal = 1;
range.has_start_ordinal = false;
ovstage_read_handle_t read = OVSTAGE_INVALID_READ_HANDLE;
enq = ovstage_read_attributes(stage, query, &attr, 1, range, &read);
waitOp(stage, enq, "read_attributes");
ovstage_read_group_t group{};
status = ovstage_fetch_read_next(stage, read, OVSTAGE_TIMEOUT_INFINITE, &group);
check(stage, status, "fetch_read_next");
if (group.data.tensor_count != 1 || !group.data.tensors[0].data)
{
std::fprintf(stderr, "unexpected read layout\n");
return EXIT_FAILURE;
}
const float* out = static_cast<const float*>(group.data.tensors[0].data);
std::printf("read back ordinal %llu: %.1f %.1f %.1f\n", (unsigned long long)group.ordinal, out[0], out[1], out[2]);
ovstage_release_group(stage, &group); // the tensor data is only valid until the group is released
Next Steps#
Explore the Examples.
Refer to the C API Reference for the full C API reference.