0

I'm struggling with an error compiling WASM including cmath library.

What I need to do is being able to use sqrt function in JavaScript... If I delete the sqrt function and the cmath library, all works fine... Can someone, help me to understand what I'm doing wrong?

Here the C++ code:

#include <cmath>
extern "C" {
  int Sum(int a, int b) {
    return a + b;
  }

  int sub (int a, int b){
    return a - b;
  }

  double root (int a){
    return sqrt(a);
  }
}

This is what I run on terminal to generating the WASM file

em++ -std=c++2b "PATH_TO_CPP_FILE" -Oz -s WASM=1 -s SIDE_MODULE=1 -s BINARYEN_ASYNC_COMPILATION=0 -o "PATH_TO_A_FOLDER\FILENAME.wasm"

This is the JavaScript code I'm usign:

const importObject = {
    module: {},
    env: {
      memory: new WebAssembly.Memory({ initial: 256 }),
    }
  };

  WebAssembly.instantiateStreaming(
    fetch('main.wasm'),
    importObject
  ).then(result => {
    const Sum = result.instance.exports.Sum;
    const sub = result.instance.exports.sub;
    console.log(Sum(4, 5));
    console.log(Sum(10, 10));
    console.log(sub(20, 10));
  });

Finally this is the error I'm currently having:

Uncaught (in promise) LinkError: WebAssembly.instantiate(): Import #0 module="env" function="_Z4sqrtIiENSt3__29enable_ifIXsr3std11is_integralIT_EE5valueEdE4typeES2_" error: function import requires a callable
  • When you `#include `, this function is strictly speaking [`std::sqrt`](https://en.cppreference.com/w/cpp/numeric/math/sqrt), not guaranteed to be available in the global namespace. Maybe this is the problem, so try `return std::sqrt(a);` instead. – heap underrun May 08 '22 at 17:46
  • Thank you @heapunderrun for your reply ! Sadly it didn't worked... Still the same error – Giuseppe D. May 08 '22 at 18:14
  • You should add Sum, sub and root to the exported functions: -s EXPORTED_FUNCTIONS=['_Sum', '_sub', '_root'] – kalwalt May 11 '22 at 20:11
  • 1
    Hi @kalwalt thank you for your reply ! I tried what you suggested, but I had a different error than. Here what I had: `Uncaught (in promise) TypeError: WebAssembly.instantiate(): Import #0 module="wasi_snapshot_preview1" error: module is not an object or function` that I solved thanks to this [question](https://stackoverflow.com/a/62778049/10413881) than I was able to use my 3 functions thanks to this [question](https://stackoverflow.com/a/56053382/10413881) The full command: `emcc "path_cpp" -o "FILENAME.HTML" -sEXPORTED_FUNCTIONS=_Sum,_sub,_root -sEXPORTED_RUNTIME_METHODS=ccall,cwrap` – Giuseppe D. May 13 '22 at 11:04

1 Answers1

0

So basically when you try to include some library in your code, you need to import that function as well in the javascript code. Simply you include it in the importObject on env property.

env:{ 
_Z4sqrtIiENSt3__29enable_ifIXsr3std11is_integralIT_EE5valueEdE4typeES2_(){}
}

Now let say you have included multiple library in your project and you want to see which all functions to be imported. You can check it on https://webassembly.github.io/wabt/demo/wasm2wat/ here you can include your wasm file and see all the functions you need to import. Also you can find the same info on browser sources tab, where you can click on the wasm file to check the information.

ruud
  • 743
  • 13
  • 22
aniket
  • 1
  • While this link may answer the question, it is better to include the essential parts of the answer here and provide the link for reference. Link-only answers can become invalid if the linked page changes. - [From Review](/review/late-answers/34805044) – XMehdi01 Aug 10 '23 at 22:27