javascriptcwebassembly

Export a structure from C to wasm?


I have a header file with the following declarations:

typedef struct {
        double *vals;
        int len;
} List;

typedef struct {
        List *list;
        int sample;
} MarkedList;

I'm compiling a C file that includes these definitions and a function that takes a const *MarkedList with:

clang --target=wasm32 -nostdlib -Wl,--export-all -Wl,--no-entry src/filename.c -o target/res/filename.wasm

I'm loading that file with:

WebAssembly.instantiateStreaming(fetch('res/mean.wasm'), {})
.then(results => {
    console.log(results)
});

The console then shows me a wasm module with instance.exports containing the function I defined, but not the structures. How can I access the structures from my javascript results object?


Solution

  • I'v changed a lot of code in figuring out how to address this, but I'll try to write out a summary of my overall solutions as best I can. Firstly, I switched to emcc over clang so that standard library C features (like malloc) work in wasm (see How to implement "malloc" in Wasm). While it's a very heavy-handed solution, I believe LTO can cut down on some unused features.

    Secondly, I've done my best to encapsulate the API of the List and MarkedList structs such that only useful functions that communicate with solely number types (including pointers) are exported to the JS, in compliance with the WebAssembly standard. So a List *malloc_list(void) and a void push_list(List *l, double v) make sense in this context, but anything with an API depending on the in-memory representation of a struct (for instance, to access an indivdual field) would be impossible.

    So while there is no widely-applicable way to export a struct, there are workarounds that keep as much as possible in the C and as little as possible in the JS, and I was able to accomplish what I needed from the List and MarkedList structs.