Skip to content

Basic Example — Zig

Source: apps/zig/example/src/main.zig | WASM demo not available — Zig 0.15 lacks wasm32-emscripten support

The Zig example demonstrates the ove module with comptime feature detection, generic types, defer-based cleanup, and catch-based error handling.

Zig patterns

Objects use Zig generics — type and size are comptime parameters:

const ove = @import("ove");
const Thread = ove.Thread;
const Queue = ove.Queue;
const Timer = ove.Timer;

var queue: Queue(u32, 8) = undefined;
var last_value: std.atomic.Value(u32) = std.atomic.Value(u32).init(0);

Queue(u32, 8) is a generic queue instantiation. std.atomic.Value(u32) provides lock-free shared state — same pattern as the Rust example's AtomicU32.

Comptime feature detection

const has_lvgl = @hasDecl(ove.ffi, "ove_lvgl_init");
const lvgl = if (has_lvgl) ove.lvgl else undefined;

const app_title = if (@hasDecl(ove.ffi, "CONFIG_OVE_RTOS_POSIX"))
    "oveRTOS(POSIX) Zig Demo"
else
    "oveRTOS Zig Demo";

@hasDecl checks at compile time whether the C FFI binding contains a symbol. This replaces #ifdef from C — the compiler eliminates dead code paths entirely.

Producer thread

fn producerThread(_: ?*anyopaque) callconv(.C) void {
    var count: u32 = 0;
    ove.log.inf("Producer started", .{});

    while (true) {
        count += 1;
        queue.send(&count, 1000) catch {
            ove.log.warn("Producer: queue full, dropped {}", .{count});
        };
        Thread.sleepMs(500);
    }
}

Error handling uses Zig's catch — the send returns an error union.

Consumer with atomic state

fn consumerThread(_: ?*anyopaque) callconv(.C) void {
    while (true) {
        var val: u32 = 0;
        queue.receive(&val, ove.WAIT_FOREVER) catch continue;
        last_value.store(val, .monotonic);

        if (val % 5 == 0) {
            ove.log.inf("Consumer: count = {}", .{val});
        }
    }
}

Entry point

export fn ove_main() void {
    ove.log.inf("Zig example: init", .{});

    queue = Queue(u32, 8).init() catch return;

    _ = Thread.spawn(producerThread, null, prio.normal, "producer", 4096) catch return;
    _ = Thread.spawn(consumerThread, null, prio.normal, "consumer", 4096) catch return;

    if (has_lvgl) {
        lvgl.init() catch return;
        createUi();
        ui_timer = Timer.initPeriodic(uiTimerCb, null, 200) catch return;
        ui_timer.start() catch {};
    }

    ove.run();
}

Key APIs demonstrated

Zig API C Equivalent Purpose
Queue(u32, 8).init() ove_queue_create Generic typed queue
Thread.spawn() ove_thread_create Thread creation with error union
Timer.initPeriodic() ove_timer_create Periodic callback timer
std.atomic.Value(u32) ove_mutex_* Lock-free shared state
@hasDecl(ove.ffi, ...) #ifdef CONFIG_OVE_* Comptime feature detection
lvgl.init() ove_lvgl_init LVGL initialization
ove.run() ove_run Start scheduler

How to build

make host.posix.example_zig
make configure && make download && make && make run