Webgl/wasm API in Zig, namespace / API design

I am porting my tinygo webgl2/wasm code over to Zig. I am very new to Zig (1 week) and struggling to understand a namespace issue. So for the following example webgl statement:

gl.clear(gl.COLOR_BUFFER_BIT);

In my main.zig I have:

const js = @import("js.zig");
const canvas = js.Canvas.init(doc.getElementById("canvas1"));
const gl = canvas.getContext("webgl2");

but this next statement is ugly:

gl.clear(js.Context3D.COLOR_BUFFER_BIT);

In my js.zig I have such a struct:

pub const Context3D = struct {
    ptr: usize,
    pub fn init(ptr: usize) Context3D {
        return Context3D{
            .ptr = ptr,
        };
    }
    pub const COLOR_BUFFER_BIT = 0x00004000;

    pub fn clear(self: Context3D, mask: u32) void {
        call_PNV(self.ptr, "clear", mask);     
    }

    //rest of webgl API
};

I was thinking I could add to my struct, something like this:

usingnamespace enum(u32) {
    DEPTH_BUFFER_BIT = 0x00000100,
    STENCIL_BUFFER_BIT = 0x00000400,
    COLOR_BUFFER_BIT = 0x00004000,
    };

and then the wasm call would be:

call_PNV(self.ptr, "clear", @enumToInt(mask));

But I cant find a way to get this to work. Probably this allows at best to access the enum values via the struct Type:

Context3D.COLOR_BUFFER_BIT

but not using an instance of of the struct:

gl.COLOR_BUFFER_BIT

Is there a more idiomatic way to solve this API design? I quite liked the idea of the encapsulation within the struct of the webgl context handle, all typesafe-ish methods, and the relevant constants…

Don’t use usingnamespace, just define the values as an enum, like you did, and then you can just write this at the call site:

gl.clear(.COLOR_BUFFER_BIT);

Great! that worked, thanks, but is there any way that I can achieve the ‘gl’ prefix. I want to match the original API as close as possible, eg.

gl.clear(gl.COLOR_BUFFER_BIT | gl.DEPTH_BUFFER_BIT);

I am thinking enums might not be the best solution anyway, since some constants are re-used across the API. So probably I will need just a big list of ‘pub const’ in my struct, but not unless I can address with with a gl. prefix. I hope that makes sense :slight_smile:

Uhm sorry I don’t have any more suggestions, other than you should probably take into consideration that when creating Zig bindings you also need to take into account what it means to be idiomaitic in Zig, and not just optimize for what C does because, if anything, there are at the very least quite a few things in C that are much more awkward to port 1:1 to Zig.

That said, I honestly don’t know have any direct recommendation for this specific case. Hopefully someone else will be able to give more recommendations.

I should have mentioned I am on Zig 0.7.1 (I think the last supporting my macos 10.12 Sierra). Anyway I appreciate your time looking into this for me. I will post back here if I find a good solution.

I did think I could maybe abandon the ‘gl’ struct all together, and then on my import statement, import everything into gl namespace:

const gl = @import("gl.zig");

but it feels wrong…