Using EMCC and WASM on the web, what is the best way to utilize a C function?

I am currently working on a basic website that showcases the outcome of a function call from a javascript file that interacts with a WASM file. Here are the files I have set up:

Makefile

FILES = add.c
OUTPUT = MyWasmLib
CC = emcc
EMCC_VERSION := $(shell command -v $(CC) 2> /dev/null)
EMCC_FLAGS = -s EXPORT_ALL=1 -s EXPORTED_RUNTIME_METHODS='["cwrap"]' -s ALLOW_MEMORY_GROWTH=1  -s EXPORT_ES6=1 -sMODULARIZE

all: check_emcc $(OUTPUT)

check_emcc:
ifndef EMCC_VERSION
    $(error "emcc is not installed. please install emscripten.")
endif

$(OUTPUT): $(FILES)
    $(CC) $(EMCC_FLAGS) -o <a href="/cdn-cgi/l/email-protection" class="__cf_email__" data-cfemail="8fabcfa1e5fc">[email protected]</a> $(filter %.c, $(FILES))

clean:
    rm -i $(OUTPUT).js $(OUTPUT).wasm

.PHONY: all check_emcc clean

add.c

#include <emscripten.h>

EMSCRIPTEN_KEEPALIVE
int add(int a, int b) {
    return a + b;
}

wasm_mjs_interface.js

import { default as MyWasmLib } from "./MyWasmLib.js";

let addWasmFunction;

let WASM_initialized;
const initializeWASM = () => {
    WASM_initialized = new Promise((resolve, reject) => {
        MyWasmLib.onRuntimeInitialized = () => {
            try {
                addWasmFunction = MyWasmLib.cwrap(
                    "add", "number", ["number", "number"]
                );

                resolve();
            }
            catch (error) {
                reject(error);
            }
        };
    });
};

initializeWASM();

export const WASM_add = async (a, b) => {
    await WASM_initialized;
    try {
        return addWasmFunction(a, b);
    }
    catch (error) {
        console.error("Error calling add function in WASM: ", error);
        throw error;
    }
};

index.js

import { WASM_add } from "./wasm_mjs_interface.mjs";

async function loadWasmAdd() {
    try {
        const result = await WASM_add(5, 3);
        console.log("WASM addition result: ", result);
        document.getElementById("result").textContent = `${result}`;
    }
    catch (error) {
        console.error("Error performing WASM addition: ", error);
    }
}

if (document.readyState === "loading") {
    window.addEventListener("DOMContentLoaded", loadWasmAdd);
} else {
    loadWasmAdd();
}

index.html

<!DOCTYPE html>
<html lang="en">
    <head>
        <title>WASM Module Example</title>
        <script type="module" src="./index.js"></script>
    </head>
    <body>
        <p id="result"></p>
    </body>
</html>

I have set up a basic python server using

python3 -m http.server 8000

To view the server, I am using

firefox 0.0.0.0:8000/index.html

The issue I am encountering is that nothing seems to be happening in the actual console or on the page. While I can see a GET request for index.html, MyWasmLib.js, and wasm_mjs_interface.mjs in the console, there are no errors displayed and no content appearing in the browser where the p tag is located.

Answer №1

If you're encountering the issue of not loading the .wasm file, remember that you must first load it before initializing everything else.

Consider implementing a solution similar to the following:

// importWasm.js
Module = {};    // initialize Module to store the wasm code
loadWASM = () => {
  
  return new Promise((resolve) => {
    
    fetch('myWasm.wasm')    // fetch the .wasm file
      .then(response => response.arrayBuffer())
      .then((buffer) => {    // return ArrayBuffer
        Module.wasmBinary = buffer;   // assign buffer to Module
        
        const script = document.createElement('script');
        script.src = 'myWasm.js';   // set script source
        
        script.onload = () => {    // when script is loaded
          console.log("Emscripten loaded successfully.");
          resolve(Module);    // return Module
        };
        document.body.appendChild(script); // append script to DOM
      });
  });
};

For a detailed example, check out this resource: https://medium.com/@matzewagner/creating-a-webassembly-work-environment-c584b15fdb73

Similar questions

If you have not found the answer to your question or you are interested in this topic, then look at other similar questions below or use the search

Using Geolocation in HTML5 and JavaScript

Currently, I am working on my debut mobile web application and have successfully integrated Google Maps into it using Geolocation JavaScript API version 3. Now, I am looking to add a button that, when clicked by the user, centers the map on my location o ...

Convert the JSON data into the specified format using JavaScript

Is there a way to transform JSON data like this in JavaScript? data = [{acquired: "2018-03-09T22:49:52.935Z", mean_ndvi: -0.0483685} {acquired: "2018-02-13T22:49:16.568Z", mean_ndvi: 0.00595065} {acquired: "2018-04-01T22:50:30.912Z", mean_ndvi: -0.033455} ...

Decoding JSON data in a Webmethod from an AJAX call

I am faced with a challenge regarding passing a JSON object from JavaScript to a VB.Net WebMethod via an ajax request and then attempting to deserialize it. Despite successfully passing the object, I encounter an error during deserialization: Error convert ...

Middleware in Express not producing results

Here is the code I am currently using: var express = require('express'); var app = express(); app.use(express.bodyParser()); app.use(express.cookieParser()); var port = Number(process.env.PORT || 5000); app.get('/test/:id', function(r ...

Executing various axios requests to retrieve diverse data and populating multiple sections of the user interface in React Native

I am struggling to display various categories of movies on the same screen, such as "POPULAR MOVIES", "RECOMMENDED MOVIES", and "NEWEST MOVIES". I have been able to retrieve data for the "POPULAR MOVIES" section using an API call, but I'm unsure of th ...

Validation of editable cells in a material table

I'm currently using Material Table for displaying table data and I'm looking to implement validation on the surname field. When the length of the surname is less than 3, I want to display an error message in red below the input field saying "too ...

Conditional styling in React class components depending on the props provided

Dealing with older versions of material-ui that cannot be updated. I'm attempting to modify the background of the Paper component based on various prop combinations without relying on the makeStyles HOC. Is this achievable? The issue seems to lie in ...

VueX threw an error stating that it cannot read property 'getters' because it is undefined in Nuxt.js

Just starting out with Vuejs and Nuxt.js. I recently set up a Nuxt project but encountered an error when trying to run it: https://i.sstatic.net/ROtOs.png Any assistance would be greatly appreciated. Thank you. ...

Understanding JSON Parsing in Jade

I am facing a challenge with handling a large array of objects that I am passing through express into a Jade template. The structure of the data looks similar to this: [{ big object }, { big object }, { big object }, ...] To pass it into the Jade templat ...

Modifying text on input buttons using Javascript

Including product names, text forms, and buttons on a webpage is essential for showcasing products effectively. Each product is assigned an ID such as p1, p2, etc., while the input types are identified by i1, i2, etc. When users enter information into the ...

Retrieve JSON Object using a string identifier

I created a script that takes the ID of a link as the name of a JSON dataset. $('.link').click(function() { var dataset = $(this).attr("id"); for (var i = 0; i < chart.series.length; i++) { chart.series[i].setData(lata.dataset ...

Guide to setting up Gatsby CLI and Gatsby version 2

Currently, I am working on a project that utilizes Gatsby v2 in its package.json file. However, to run the project, I need to globally install Gatsby-cli as per the documentation. Strangely, the global installation of Gatsby-cli also installs Gatsby v4, ca ...

Inconsistent rendering issue identified in AngularJS when updating arrays with ui-router

I'm leveraging ui-router to navigate to specific subpages in my application: var myApp = angular.module("myApp",['ui.router']); myApp.config(function($stateProvider, $urlRouterProvider) { $stateProvider .state('usergroups&apos ...

What could be causing the second switchMap to be triggered repeatedly upon subscription?

Check out the code snippet below for reproducing the issue: import { defer, BehaviorSubject, of } from "rxjs"; import { shareReplay, switchMap } from "rxjs/operators"; const oneRandomNumber = defer(() => of(Math.floor(Math.random() ...

Error encountered while importing animation from 3ds Max to Collada format and then to Three.js: "Scaling exceeds limits"

After exporting a rigged and animated model to collada using the opencollada exporter from 3ds max, everything seems to load fine and the animation runs smoothly. However, with each loop of the animation, I encounter the following warning: THREE.Animation ...

Effortlessly move and place items across different browser windows or tabs

Created a code snippet for enabling drag and drop functionality of elements within the same window, which is working smoothly. var currentDragElement = null; var draggableElements = document.querySelectorAll('[draggable="true"]'); [].forEach ...

What is the best way to retrieve a floating point array from a function?

The values of k in the output display as 0.000, but they should reflect the true values returned by funcTest(). #include <stdio.h> #include <stdlib.h> float *funcTest(int *a, int size) { float p[size]; int i; for(i=0; i< size; ...

How can I dictate the placement of a nested Material UI select within a popper in the DOM?

Having trouble placing a select menu in a Popper. The issue is that the nested select menu wants to mount the popup as a sibling on the body rather than a child of the popper, causing the clickaway event to fire unexpectedly. Here's the code snippet f ...

When the dependency value transitions from 1 to 0, useEffect fails to trigger

I'm really puzzled by how useEffect behaves in this scenario: Check out this code snippet: const numVertices = selectionProvider.verticesSelectionProvider.count; console.log('RENDER ---> COUNT = ', numVertices); useEffect(() => { ...

Animating background color change with scroll in React using fade effect

Can someone help me with implementing a fading animation for changing the background color on scroll in React? I have successfully achieved the background change effect, but I'm struggling to incorporate the fading effect. import React from "reac ...