Libove Blog

Personal Blog about anything - mostly programming, cooking and random thoughts

Building WASM library with Zig

This is written for Zig 0.14.1.

For my chromahack project I've used zig to implement the language. To integrate this into an interactive web app I had to compile it to WASM.

Function Definition

The original function I wanted to export as WASM has this signature:

pub fn render_point(program: []const u8, t: f32, x: f32, y: f32) [3]f32

This was a problem as the WASM target does not support the types []const u8 and [3]f32 as function parameter/return type. Therefore I've created a new function (creatively called render_point_2) to wrap my original implementation:

export fn render_point_2(program: [*]const u8, len: usize, t: f32, x: f32, y: f32, result: [*]f32) void {
    const r = render_point(program[0..len], t, x, y);
    result[0] = r[0];
    result[1] = r[1];
    result[2] = r[2];
}

The program is now passed as a pointer to an array + its length. The function no longer has a return value, but writes the result to a provided array address. The caller has to ensure that the array can store 3 floating point values.

Also note the export keyword. I've missed this and spent an hour wondering why my WASM file had no exported function.

Building WASM

To build the WASM file you can either use the zig build-exe command or integrate it into your build.zig file.

The command zig build-exe src/root.zig -target wasm32-freestanding -fno-entry -rdynamic -OReleaseFast will create the WASM file in your project folder.

To build the WASM file via zig build add the following block to your builg.zig file. This will create the file in zig-out/bin. (based on this gist from trasstaloch )

const wasm = b.addExecutable(.{
	.name = "lib",
	.root_source_file = b.path("src/root.zig"),
	.target = b.resolveTargetQuery(std.Target.Query.parse(
		.{ .arch_os_abi = "wasm32-freestanding" },
	) catch unreachable),
	.optimize = optimize,
});
wasm.entry = .disabled;
wasm.rdynamic = true;
b.installArtifact(wasm);

It is also possible to copy further assets into the output directoy, such as your HTML and JavaScript files.

// copy web stuff
b.installBinFile("index.html", "index.html");
b.installBinFile("assets/favicon.png", "favicon.png");

#zig #dev #wasm





Interactions

Liked by πŸ‡΅πŸ‡Έ servisoficial πŸ‡²πŸ‡½πŸ‡·πŸ‡Ί

Reply from Libove Blog: Passing Strings and Arrays between JS and WASM
(Original Post)

Passing Strings and Arrays between JS and WASM