3

I am writing a webassembly demo in C to match a similar demo I wrote in zig.

I am currently able to call C functions from JS, and interact with shared memory on either side. However, I can't seem to be able to expose JS variables and functions to the C program.

Is anybody familiar with writing C this way? I wonder if the undefined symbols are getting optimized out somehow.

I'm using zig cc (i.e. clang) to compile to wasm on zig version 0.13.0-dev.351+64ef45eb0, using clang 16.0.0 on macos Sequoia 15.0.1 (aarch64).

This is the code I've written thus far:

resource.c

#include <stdlib.h>

void print_test(void); // the function I want to use

const unsigned char heap[4096];

int __attribute__((export_name("memstart")))
memstart() {
    return (int)&heap;
}

int __attribute__((export_name("return5")))
return5(int p) {
    return 5 * p;
}

int __attribute__((export_name("entryAt")))
entryAt(int p) {
    print_test();
    return heap[p];
}

index.html


<!DOCTYPE html>
<html lang="en">
    <head>
        <title>For Stephen</title>
    </head>

    <body>
        <input id="input" type="number" placeholder="int param..."></input>
        <input id="bytes" placeholder="bytes..."></input>
        <pre id="output">output goes gere</pre>
        <button id="button_r5">Return 5</button>
        <button id="button_nth">Get nth byte</button>
        <canvas id="my_canvas"></canvas>
        <script>
            const c = {};
            const encoder = new TextEncoder();
            const decoder = new TextDecoder();

            const importObject = {
                "env": {
                    "print_test": () => console.log("test print")
                }
            };

            WebAssembly.instantiateStreaming(fetch("resource.wasm", importObject))
            .then(result => {
                const {memory, memstart, return5, entryAt} = result.instance.exports;
                console.log(memstart);
                c.buffer  = new Uint8Array(memory.buffer, memstart());
                c.return5 = return5;
                c.entryAt = entryAt;
            });

            const button_r5  = document.getElementById("button_r5");
            const button_nth = document.getElementById("button_nth");
            const input  = document.getElementById("input");
            const bytes  = document.getElementById("bytes");
            const output = document.getElementById("output");

            button_r5.addEventListener("click", ()=>{
                output.textContent = c.return5(input.value);
            });

            button_nth.addEventListener("click", ()=>{
                c.buffer.set(encoder.encode(bytes.value));
                output.textContent = c.entryAt(input.value);
            });
        </script>
    </body>

</html>

Build command

zig cc -target wasm32-freestanding -g resource.c -lc -Wl,--no-entry -o resource.wasm
2
  • Maybe use __attribute__((import_module("env"), import_name("print_test"))) void print_test();? Commented Feb 17 at 6:51
  • @Inkeliz this works! Add it as an answer and I'll accept it. Commented Feb 17 at 19:47

1 Answer 1

1

You can use some attributes to import functions from JavaScript, that will depends on the compiler.

Using Emscripten you can set EM_IMPORT(NAME). That is equivalent of __attribute__((import_module("env"), import_name(#NAME))) (source-code).

Considering that Zig also uses LLVM, you can also use the same attribute:

__attribute__((import_module("env"), import_name("print_test"))) void print_test();

However, if it doesn't work (maybe it's not using Zig compiler), you might have some other flavours:

void print_test() __attribute__((
    __import_module__("env"),
    __import_name__("print_test")
));

__attribute__((__import_name__("print_test"))) void print_test();

That are based on other languages/compilers, such as SwiftWasm and .NET-NativeLLVM (all based on LLVM).

Sign up to request clarification or add additional context in comments.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.