Interfacing C/zig with translate-c: can I filter out builtin functions from translate-c output?

I’m using translate-c to generate a zig “header” from a C .h file like so:

zig translate-c src/gfxutil/joystick.h > src/gfxutil/joystick_c.zig

The contents of joystick.h are basically just:

#pragma once

typedef struct {
    int idx;
    int lx;
    int ly;
    int lz;
    int rx;
    int ry;
    int rz;
    unsigned int buttons;
} win32_read_result;

extern void win32_joystick_init(void);
extern win32_read_result win32_joystick_read(void);

The output zig file contains all the Zig built ins and is over 400 lines long:

pub const __builtin_bswap16 = @import("std").zig.c_builtins.__builtin_bswap16;
pub const __builtin_bswap32 = @import("std").zig.c_builtins.__builtin_bswap32;
pub const __builtin_bswap64 = @import("std").zig.c_builtins.__builtin_bswap64;
pub const __builtin_signbit = @import("std").zig.c_builtins.__builtin_signbit;

Is there a way to stop translate-c from including the builtins in output? I’d like the output to contain only my own C declarations? I’m checking these outputs into Git and it’d be nice to cut down on the # of declarations in my import zig files for both cleanliness and readability.

I first tried using @cImport but that seems to only work with system include paths and not .c/.h files in my own game projects.

Hi! I’m not aware of any way to remove the builtins from the translate-c output (though I haven’t looked into it).

I first tried using @cImport but that seems to only work with system include paths and not .c/.h files in my own game projects.

But you should be able to use @cImport() with local paths. This would be the recommended approach. I do that in my projects (for example, I do a @cImport() for my lzrw.h header in open-reckless-drivin/src/lzrw.zig at master · natecraddock/open-reckless-drivin · GitHub).

If my example code doesn’t help, what isn’t working with your attempts to @cImport() your local headers?

Below is the error that I get. FWIW, using #include <header> is not ideal, it should be #include "header" but seems to be not what Zig’s doing.

But I was able to fix it too. In my case, I have split my project into “utils” (lib) package and “main” (exe). I had added the include path for “utils” with lib.addIncludePath("src/gfxutil/"). With just this, building main exe fails as below. But if I also add exe.addIncludePath("src/gfxutil/") to the exe build options, it works. This is a little surprising, I would’ve expected it to be enough to specify the include path only for the library I’m building and that’d be enough. It’s probably not working as intended…?

src\gfxutil\joystick.zig:3:12: error: C import failed
const c2 = @cImport({
           ^~~~~~~~
referenced by:
    initJoystick: src\gfxutil\joystick.zig:9:5
    init: src\main.zig:267:21
    remaining reference traces hidden; use '-freference-trace' to see all reference traces

<snip>\67da55fd196b7c4b10285f836db20262\cimport.h:1:10: error: 'joystick.h' file not found
#include <joystick.h>
         ^

It’s hard to debug without more context on your project. Is lib a statically linked library that you link to exe? If so, both would need C headers, and using exe.addIncludePath() is necessary.

I agree. I’ll craft a gist with an example tonight.

1 Like

I made a github repo that contains a buildable example:

  • the main “exe”
  • a library called “misclib” that’s added as an anonymous module into exe deps.

I’m not sure if this is actually the right way to build an exe with some dependency zig libraries, it’s just something I adapted from the Sokol gfx pacman project.

Out of the box the project should succeed to build. It will call a function in the C file. Commenting out this line breaks the build.

I’d expect misclib to build a library that could be used by the main exe project without the exe build configuration caring about what .h files the dependency library happens to include. I don’t need the exe build to muck about with .h include path when I’m using translate-c (my original post). But maybe I should be using packages instead?

1 Like

Thanks for making an example, this makes things much more clear. I think part of the confusion here comes from the Zig package manager still being incomplete.

You are correct. Ideally you shouldn’t need the exe.addIncludePath("src/misclib"); line. That is a current limitation of modules. This PR Add CompileStep APIs to Build.Module. by AdamGoertz · Pull Request #14731 · ziglang/zig · GitHub should fix that (I’m waiting on this to be fixed as well for my ziglua project). Here is why it currently fails:

In your project misclib is a module. That module includes a @cImport(), so the install header path needs to be specified twice. Once for the library include (inside misc.c) and another time in the Zig module (in misclib/main.zig).

The linked PR will update things so modules can include headers, artifacts, and more. So you could “bundle” the Zig module and the compiled artifact into a single module and then more easily add the module as a single unit. Hopefully that all makes sense!

Now that said. Without knowing the specifics of your project it is hard to tell, but unless your gfxutil module is intended to be used in other projects, you might be making things harder on yourself by splitting things into modules.

1 Like

Thank you very much!

I agree that simply not building parts of my game into a library might simplify things. I tried to keep some things a little more separate in case I reuse them in future projects but it shouldn’t be too hard to reuse them either way.

BTW Ziglua looks great! I’ll probably use it in my future game projects. :slight_smile:

1 Like

You’re welcome, happy to help!

I agree that simply not building parts of my game into a library might simplify things. I tried to keep some things a little more separate in case I reuse them in future projects but it shouldn’t be too hard to reuse them either way.

Yeah. I would just keep those things in separate .zig files, or even separate subdirectories. Then you can easily pull it into a separate repo in the future if needed.

BTW Ziglua looks great! I’ll probably use it in my future game projects. :slight_smile:

:smile: