Wasmtime bindings for Zig
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
copygirl 4bc1ded481 Avoid alloc in wrapped func when returning error 5 months ago
src Avoid alloc in wrapped func when returning error 5 months ago
.editorconfig Initial commit 8 months ago
.gitignore Initial commit 8 months ago
README.md Allow wrapped function to return error union 8 months ago
UNLICENSE.txt License looks better with line wraps 8 months ago
build.zig Val.fromValue accepts type param, fix tests 8 months ago
build.zig.zon Package management fix 8 months ago

README.md

wasmslime

.. is a library providing Wasmtime bindings for use with the Zig language. This is my first project I've tackled with Zig, as I wanted to play around with WebAssembly for sandboxing reasons, and the libraries I have found are both outdated and incomplete. Though they did provide some starting help.

Of course, this library too is likely very much incomplete, maybe even broken. I just wanted to share it as I'm quite proud and perhaps someone else finds some use in it. Feel free to yoink anything from wasmslime as you see fit.

Example

const wat_bytes =
    \\(module
    \\  (func $hello (import "env" "print_hello"))
    \\  (func (export "main") (call $hello)))
;

fn print_hello() !void {
    const stdout = @import("std").io.getStdOut().writer();
    try stdout.print("Hello, Slime!\n", .{});
}

pub fn main() !void {
    const wasm = @import("wasmslime");
    // Should deinit Wasm objects, but this is omitted for brevity.
    var engine = try wasm.Engine.initDefault();
    var module = try wasm.Module.initFromWat(engine, wat_bytes, null);
    var linker = wasm.Linker.init(engine);
    try linker.defineFuncFromFn("env", "print_hello", print_hello, null);
    var store = wasm.Store.init(engine);
    var context = store.getContext();
    var instance = try linker.instantiate(context, module, null);
    const run_func = try instance.get(context, "main", wasm.Func);
    try run_func.call(context, .{}, void, null);
}

Setup as Dependency

Currently requires Wasmtime to be installed as a system library. Unsure about the possibility of statically linking it instead, and the up- and downsides that come with that. I may look into this in the future.

wasmslime uses Zig version 0.11 and thus makes use of its new Package Management feature. Since this is a pretty new feature that currently isn't documented beyond what's shared in the release notes, I'll give a brief overview of how to add it as a dependency to your project.

build.zig.zon

.{
    .name = "my_amazing_project",
    .version = "0.1.0",
    .dependencies = .{
        .wasmslime = .{
            .url = "https://git.mcft.net/copygirl/wasmslime/archive/main.tar.gz",
            .hash = "00000000000000000000000000000000000000000000000000000000000000000000",
        },
    },
}

Providing an invalid hash will make the build system complain about what it should actually be. Keep in mind the string needs to be the correct length, however. This way I don't have to update the README each commit.

Downloaded packages end up in ~/.cache/zig/. If the hash already matches an existing package here, it will be used regardless of the source URL. If you run into issues, you could consider clearing Zig's cache folder.

build.zig

...
const exe = b.addExecutable(...);

const wasmslime = b.dependency("wasmslime", .{ .target = target, .optimize = optimize });
exe.addModule("wasmslime", wasmslime.module("wasmslime"));
exe.linkLibrary(wasmslime.artifact("wasmslime"));

b.installArtifact(exe);
...