0

I used i32 binding perfectly between zig/wasm and JavaScript as below:

//main.zig
const std = @import("std");
extern fn print(a: i32) void;

export fn add(a: i32, b: i32) i32 {
    print(a + b); // calling the JavaScript function
    return a + b;
}

Compiled it as:

zig build-lib -O ReleaseSmall -target wasm32-freestanding main.zig -dynamic

And called it from nodejs as:

// index.js
import fs from "fs"
const source = fs.readFileSync("main.wasm")
const tyoedArray = new Uint8Array(source)

const importObject = {
    env: {
        print: function(x) { console.log(x); } // map the zig function print to the JS function console.log(x)
    },
  };
  
const resuult = await WebAssembly.instantiate(tyoedArray, importObject);
console.log(`a + b = ${resuult.instance.exports.add(2,3)}`);

And got the output as:

5 // printed from Zig print(a + b); that is mapping with JavaScript print: function(x) { console.log(x); }
a + b = 5 // printed from Javascript console.log(`a + b = ${resuult.instance.exports.add(2,3)}`);

What if instead the extern fn print(a: i32) void; I want to defined a function signature as:

// new.zig
extern sayHello([]const u8) []const u8;

And mapping it with a JS function like:

//new.js
const importObject = {
    env: {
        print: sayHello(name) {  
                  return `Hello ${name}` 
               };
    },
  };
Hasan A Yousef
  • 22,789
  • 24
  • 132
  • 203

1 Answers1

0

I think the only way to pass a pointer from wasm to js is as an i32. On the js side the wasm's memory/address space is contained in a buffer object and the pointer is an offset into that buffer. Here is an example with an i32 array rather than u8 but it's pretty much the same:

const N: u32 = 1024;
var buf: [N]i32 = undefined;

export fn getPtr() i32 {
    return @intCast(i32, @ptrToInt(&buf));
}

export fn getSize() i32 {
    return @intCast(i32, N);
}

And then on js side:

const myBuf = new Int32Array(
    result.instance.exports.memory.buffer, 
    result.instance.exports.getPtr(), 
    result.instance.exports.getSize()
);

For u8 you'd want to use Uint8Array and then convert that into a string.

Gregor Budweiser
  • 218
  • 3
  • 10