【问题标题】:Rust wasm32-unknown-unknown Math functions not linkingRust wasm32-unknown-unknown 数学函数未链接
【发布时间】:2018-06-08 09:37:48
【问题描述】:

我正在为 Rust 尝试新的 wasm32-unknown-unknown 目标,但在调用数学函数(例如 sin、cos、exp、atan2)时遇到问题。

Cargo.toml:

[package]
name = "wasm_math"
version = "0.1.0"
authors = ["..."]

[lib]
path = "src/lib.rs"
crate-type = ["cdylib"]

[dependencies]

src/lib.rs:

#[no_mangle]
pub extern "C" fn invoke_sin(x: f64) -> f64 {
    x.sin()
}

index.html:

<!doctype html>
<html lang="en">
  <head><meta charset="utf-8"><title>Wasm Math</title></head>
  <body></body>
  <script>
    const imports = { env: { } };
    fetch("target/wasm32-unknown-unknown/release/wasm_math.wasm").then(response =>
      response.arrayBuffer()
    ).then(bytes =>
      WebAssembly.instantiate(bytes, imports)
    ).then(results => {
      alert(results.instance.exports.invoke_sin(1.0));
    });
  </script>
</html>

我用命令构建项目

cargo build --release --target wasm32-unknown-unknown

当我在 Firefox 中打开 html 文件时,出现以下错误:

LinkError: import object field 'sin' is not a Function

我的设置有问题吗?或者这是 Rust/WebAssembly/Firefox 中的一个缺点?我可以手动将 sin 函数添加到 javascript 中的 imports.env 对象中,但这看起来很笨拙,我必须对我使用的每个数学函数都这样做。有没有更好的办法?

我正在使用 nightly Rust 工具链(nightly-x86_64-unknown-linux-gnu rustc 1.24.0-nightly (cddc4a62d 2017-12-26))和 Firefox 57.0.1(64 位)。

【问题讨论】:

    标签: rust webassembly


    【解决方案1】:

    根据WASM FAQ sin 不包括在内。

    •WebAssembly 不包含其自己的数学函数,如 sin 、 cos 、 exp 、 pow 等。 WebAssembly 对此类函数的策略是允许它们在 WebAssembly 本身中作为库例程实现(请注意,x86 的 sin 和 cos 指令缓慢且不精确,无论如何现在通常都避免使用)。希望在 WebAssembly 上使用更快且精度更低的数学函数的用户只需选择一个数学库实现即可。

    Rust 似乎依赖 LLVM 来提供 sin (f64 impl here),而 WASM 却没有。我认为 LLVM 应该将其作为 llvm.sin.f64 内在函数的一部分提供,但似乎他们不保证每个 https://llvm.org/docs/LangRef.html#llvm-sin-intrinsic 的每个目标都能实现(强调我的):

    这是一个重载的内在函数。您可以在任何浮点或浮点类型的向量上使用 llvm.sin。 但并非所有目标都支持所有类型。

    也许,鉴于此,Rust 应该考虑自己实现 sin

    【讨论】:

      【解决方案2】:

      Kyle 对诊断很准确。我将添加两个建议。


      我知道您说过您不想手动将 Math 函数添加到您的导入对象中,但这样做也不错:

      let mathImports = {};
      for (let name of Object.getOwnPropertyNames(Math))
        if (typeof Math[name] === "function")
          mathImports[name] = Math[name];
      

      棘手的事情是在常规导入之前弄清楚如何这样做(这样它们就不会覆盖你已经拥有的任何东西),并弄清楚将导入放在哪个 module 中(因为 WebAssembly 导入有一个命名空间规范调用module,然后是您在错误消息中看到的field,FWIW Safari 中的错误消息将同时包含modulefield)。


      您可以将 C 库的子集构建到 WebAssembly 中,并将其用作导入对象的一部分。我有一个可用的musl libc 端口。 WebAssembly waterfall 构建和使用它,构建are in the waterfall's source 的说明。

      再一次,将其值放入导入对象中很难做到正确。我会使用WebAssembly.Module.exports 遍历模块的导出并确保名称修饰是正确的(看起来您的代码直接期望sin,并且通常C 名称在开头带有额外的下划线)。然后和上面一样,将它们添加到一个导入对象中,并得到module / field 对。

      【讨论】:

      猜你喜欢
      • 2021-08-26
      • 2021-05-20
      • 1970-01-01
      • 1970-01-01
      • 2014-12-17
      • 2015-09-13
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多