Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

C interoperability: zero-init and partial initialization for imported C structs? #1031

Closed
floooh opened this issue May 31, 2018 · 3 comments
Closed

Comments

@floooh
Copy link
Contributor

floooh commented May 31, 2018

Hi, I'm attempting to use my 3D-API wrapper sokol_gfx.h from zig, I got pretty far (importing the C header works, linking with the C implementation source also works), but now I'm hitting a snag when trying to setup 'option-bag structs' that are handed to the sokol_gfx API.

It looks like zig requires that all struct members must be initialized when the struct is 'instantiated', sokol_gfx uses an 'option bag philosophy': non-initialized struct members are assumed to be zero-initialized, which for sokol-gfx indicates that default-values are to be used for such fields. This works nicely with C99-style designated initialization, which sets missing fields to zero.

For instance there are structs like sg_pipeline_desc, which all in all have dozens of members (in embedded structs): https://github.com/floooh/sokol/blob/a3057b13ba38d2d554a7f04e063f6550b2cc8bcb/sokol_gfx.h#L1422

Usually, only a small number of sg_pipeline_desc members are initialized, for instance:

    sg_pipeline pip = {
        .layout = {
            .buffers[0].stride = 28,
            .attrs = {
                [0] = { .name="position", .format=SG_VERTEXFORMAT_FLOAT3 },
                [1] = { .name="color0", .format=SG_VERTEXFORMAT_FLOAT4 }
            }
        },
        .shader = shd,
        .index_type = SG_INDEXTYPE_UINT16,
        .depth_stencil = {
            .depth_compare_func = SG_COMPAREFUNC_LESS_EQUAL,
            .depth_write_enabled = true,
        },
        .rasterizer.cull_mode = SG_CULLMODE_BACK,
    });

Currently zig complains about all missing struct members in the imported C structs, and in my case, providing an initialization for all struct members manually to 0 wouldn't make sense, the sokol_gfx API would be unusable.

Is there a simple solution to this problem which I missed? Maybe an option for the "@Cinclude()" process?

Also, what's zig's 'best practice' for such 'option-bag' APIs when written in pure zig? As far as I have seen, struct members cannot be assigned a default value, and all members must be initialized, but this gets a bit ugly if there are more than a handful members.

@andrewrk
Copy link
Member

andrewrk commented May 31, 2018

Here's the current suggestion for this:

std.mem.set(u8, ([]u8)(&pip)[0..1], 0); // set everything to zero
pip.shader = shd;
pip.index_type = SG_INDEXTYPE_UINT16;
// etc

It's a little clumsy because we want to encourage setting every field. May be it's not so bad to explicitly set every field to zero?

@floooh
Copy link
Contributor Author

floooh commented May 31, 2018

I'll play around with it and see how it feels. Maybe it makes sense to write a small zig wrapper module for sokol_gfx which hides things like the std.mem.set... Thanks for the quick response :)

@floooh floooh closed this as completed May 31, 2018
@mrec
Copy link

mrec commented Jun 18, 2018

Did you (Andre) have any luck wrapping this with something that preserves the nice declarative flow of the original? I'm wondering whether this might be another motivating use case for #485

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

3 participants