cd /news/developer-tools/raylib-6-2-ported-to-zig-with-every-… · home › topics › developer-tools › article
[ARTICLE · art-151388] src=ziggit.dev ↗ pub= topic=developer-tools verified=true sentiment=↓ negative

Raylib 6.2 ported to Zig, with every example checked against C (now running in the browser too)

A developer has ported raylib 6.2 to Zig, checking every example against the original C version and running the library in the browser via WebAssembly. The port is a direct C-to-Zig translation that calls libc functions such as fopen, fread and memcpy through extern declarations rather than using Zig's optionals, error unions and allocators, and commenters criticized it as "C code written with Zig keywords" that could teach bad habits.

read2 min views1 publishedOct 16, 2026
// stdio FILE handling via opaque pointer
const FILE = anyopaque;
extern fn fopen([*c]const u8, [*c]const u8) ?*FILE;
extern fn fclose(?*FILE) c_int;
extern fn fseek(?*FILE, c_long, c_int) c_int;
extern fn ftell(?*FILE) c_long;
extern fn fread(?*anyopaque, usize, usize, ?*FILE) usize;
extern fn fwrite(?*const anyopaque, usize, usize, ?*FILE) usize;
extern fn fprintf(?*FILE, [*c]const u8, ...) c_int;
extern fn fgets([*c]u8, c_int, ?*FILE) [*c]u8;
extern fn feof(?*FILE) c_int;
extern fn sscanf([*c]const u8, [*c]const u8, ...) c_int;
const SEEK_SET: c_int = 0;
const SEEK_END: c_int = 2;

…directly calling into clib doesn’t look very Ziggy to me

Also tbh, what’s the point. The code is pretty much a straight translation from C to Zig without taking any advantage of Zig’s language features (optionals, error results, allocators, etc etc…), I’m sure Claude could do better…

Also… hrmpf look at all those C string.h and memory.h functions…

            if ((strcmp(&dp.name, ".") != 0) and (strcmp(&dp.name, "..") != 0)) {
                const pathLength = snprintf(&path, MAX_FILEPATH_LENGTH, "%s/%s", basePath, &dp.name);
                if ((pathLength < 0) or (pathLength >= MAX_FILEPATH_LENGTH)) {
                    TraceLog(LOG_WARNING, "FILEIO: Path longer than %d characters (%s...)", @as(c_int, MAX_FILEPATH_LENGTH), basePath);
                } else if (IsPathFile(&path)) {
                    if ((filter == null) or (strstr(filter, FILE_FILTER_TAG_ALL) != null) or (strstr(filter, FILE_FILTER_TAG_FILE_ONLY) != null) or IsFileExtension(&path, filter)) {
                        _ = memcpy(@ptrCast(files.paths[files.count]), @ptrCast(&path), @intCast(pathLength));
                        files.count += 1;
                    }
                } else {
                    if ((filter != null) and ((strstr(filter, FILE_FILTER_TAG_DIR_ONLY) != null) or (strstr(filter, FILE_FILTER_TAG_ALL) != null))) {
                        _ = memcpy(@ptrCast(files.paths[files.count]), @ptrCast(&path), @intCast(pathLength));
                        files.count += 1;
                    }
                    if (scanSubdirs) ScanDirectoryFiles(&path, files, filter, expectedFileCount, scanSubdirs);
                }

This is built for me and my team as a learning exercise for zig

I don’t think you’re doing yourself a favour with this approach. This is C code written with Zig keywords, not Zig code. E.g. you’re kinda missing the forest for the trees and you might just learn bad habits from this codebase.

── more in #developer-tools 4 stories · sorted by recency
── more on @raylib 3 stories trending now
sponsored brought to you by zahid.host 4,200+ EU-deployed projects
reading about agents? ship yours in a single git push.

Run your AI side-project on zahid.host

EU-based hosting, git-push deploys, automatic HTTPS, no cold starts. Free tier with a custom domain — perfect for shipping the agent you just read about.

$git push zahid main
→ Live at https://your-agent.zahid.host ✓
Get free account → Pricing
from €0/mo · no card required
LIVE [news/raylib-6-2-ported-to…] indexed:0 read:2min 2026-10-16 · —