4.7 KiB
mach/glfw - Ziggified GLFW bindings

Ziggified GLFW bindings that Mach engine uses, with 100% API coverage, zero-fuss installation, cross compilation, and more.
The main Mach repository includes this one as a git subtree
. This is a separate repo so that anyone can use this library in their own project / engine if they like!
Zero fuss installation, cross compilation, and more
Just as with Mach, you get zero fuss installation & cross compilation using these GLFW bindings. only zig
and git
are needed to build from any OS and produce binaries for every OS. No system dependencies at all.
100% API coverage, 130+ tests, etc.
These bindings have 100% API coverage of GLFW v3.3.4. Every function, type, constant, etc. has been wrapped in a ziggified API.
There are 130+ tests, and CI tests on all major platforms as well as cross-compilation between platforms:
What does a ziggified GLFW API offer?
Why create a ziggified GLFW wrapper, instead of just using @cImport
and interfacing with GLFW directly? You get:
- Errors as zig errors instead of via a callback function.
true
andfalse
instead ofc.GLFW_TRUE
andc.GLFW_FALSE
constants.- Generics, so you can just use
window.hint
instead ofglfwWindowHint
,glfwWindowHintString
, etc. - Enums, always know what value a GLFW function can accept as everything is strictly typed. And use the nice Zig syntax to access enums, like
window.getKey(.escape)
instead ofc.glfwGetKey(window, c.GLFW_KEY_ESCAPE)
- Slices instead of C pointers and lengths.
- packed structs represent bit masks, so you can use
if (joystick.down and joystick.right)
instead ofif (joystick & c.GLFW_HAT_DOWN and joystick & c.GLFW_HAT_RIGHT)
, etc. - Methods, e.g.
my_window.hint(...)
instead ofglfwWindowHint(my_window, ...)
How do I use OpenGL, Vulkan, WebGPU, etc. with this?
You'll need to bring your own library for this. Some are:
- (Vulkan) https://github.com/Snektron/vulkan-zig (also see https://github.com/Avokadoen/zig_vulkan)
- (OpenGL) https://github.com/ziglibs/zgl
Getting started
In a libs
subdirectory of the root of your project:
git clone https://github.com/hexops/mach-glfw
Then in your build.zig
add:
const glfw = @import("libs/mach-glfw/build.zig");
pub fn build(b: *Builder) void {
...
exe.addPackagePath("glfw", "libs/mach-glfw/src/main.zig");
glfw.link(b, exe, .{});
}
Now in your code you may import and use GLFW:
const glfw = @import("glfw");
pub fn main() !void {
try glfw.init();
defer glfw.terminate();
// Create our window
const window = try glfw.Window.create(640, 480, "Hello, mach-glfw!", null, null);
defer window.destroy();
// Wait for the user to close the window.
while (!window.shouldClose()) {
glfw.pollEvents();
}
}
A warning about error handling
Unless the action you're performing is truly critical to your application continuing further, you should avoid using try
.
This is because GLFW unfortunately must return errors for a large portion of its functionality on some platforms, but especially for Wayland - so ideally your application is resiliant to such errors and merely e.g. logs failures that are not critical.
Instead of try window.getPos()
for example, you may use:
const pos = window.getPos() catch |err| {
std.log.err("failed to get window position: error={}\n", err);
return;
}
Here is a rough list of functionality Wayland does not support:
Window.setIcon
Window.setPos
,Window.getPos
Window.iconify
,Window.focus
Monitor.setGamma
Monitor.getGammaRamp
,Monitor.setGammaRamp
Issues
Issues are tracked in the main Mach repository.
Contributing
Contributions are very welcome. Just send a PR to this repository.
We track the latest stable release of GLFW, if you need a newer version we can start a development branch / figure that out - just open an issue.
Once your PR is merged, if you're using Mach engine and wanting the changes there, it will be sync'd to the main repo via git subtree
.