cclangwebassemblylld

How to use WebAssembly Reference Types with Clang


I'm writing a WebAssembly application in C using Clang and LLD.

How do I write a C function that takes an externref as a parameter and how do I call this function from JavaScript? How do I use the externref value in C to call an imported function that is defined in JavaScript?


Solution

  • Support for WebAssembly reference types was added to Clang on Feb 18, 2023.

    Here is a simple program that uses reference types. A function foo is implemented in C that takes an externref as an argument and uses that argument to call a function bar which is implemented in JavaScript.

    typedef __externref_t externref_t;
    
    #define WASM_IMPORT(module, name) __attribute__((import_module(module), import_name(name)))
    #define WASM_EXPORT(name) __attribute__((export_name(name)))
    
    WASM_IMPORT("env", "bar") void bar(externref_t arg);
    
    WASM_EXPORT("foo") void foo(externref_t arg) {
        bar(arg);
    }
    

    The program can be compiled with clang foo.c -o foo.wasm -target wasm32 -mreference-types -nostdlib -Wl,--no-entry and it can be used from JavaScript as follows:

    const imports = {
        env: {
            bar(arg) {
                console.log(arg);
            }
        }
    };
    const obj = await WebAssembly.instantiateStreaming(fetch("foo.wasm"), imports);
    obj.instance.exports.foo("hello");