Skip to content

Instantly share code, notes, and snippets.

@DanB91
Last active July 26, 2025 03:31
Show Gist options
  • Save DanB91/490f85ec0e5b7828a01fd13569240fd0 to your computer and use it in GitHub Desktop.
Save DanB91/490f85ec0e5b7828a01fd13569240fd0 to your computer and use it in GitHub Desktop.
EM_ASM and EM_ASM_INT in Zig
//A Zig version of emscipten's EM_ASM and EM_ASM_INT
//WARNING: I've only tested 32-bit and 64-bit ints and floats for arguments. Haven't tested other types e.g. bool
//Example:
//em_asm(.{"World!"},
// \\const world = UTF8ToString($0);
// \\console.log(`Hello ${world}`);
// );
pub inline fn em_asm(args: anytype, comptime script: anytype) void {
_ = em_js_int(args, script);
}
pub fn em_asm_int(args: anytype, comptime script: anytype) c_int {
const scoped_script = "{" ++ script ++ "}";
const GlobalVars = struct {
extern fn emscripten_asm_const_int(code: ?[*:0]const u8, arg_sigs: ?[*:0]const u8, ...) c_int;
var x: [scoped_script.len:0]u8 linksection("em_asm") = scoped_script.*;
};
comptime var arg_sigs_buffer: [args.len + 1:0]u8 = [_:0]u8{0} ** (args.len + 1);
inline for (args, 0..) |arg, i| {
arg_sigs_buffer[i] = switch (@TypeOf(arg)) {
u8, i8, u16, i16, u32, i32, usize, isize, bool => 'i',
u64, i64 => 'j',
f32 => 'f',
f64 => 'd',
else => if (@typeInfo(@TypeOf(arg)) == .pointer)
'p'
else
@compileError(std.fmt.comptimePrint(
"Emscripten argument {} must be an integral type or a pointer. It can't be a comptime_int nor comptime_float",
.{i},
)),
};
}
const arg_sigs = arg_sigs_buffer;
const result = @call(
.auto,
GlobalVars.emscripten_asm_const_int,
.{ &GlobalVars.x, &arg_sigs } ++ args,
);
return result;
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment