为什么 Rust 中的 WASM 库必须将 crate-type 设置为 cdylib?

Mat*_*ood 6 rust rust-cargo

防锈参考状态

将产生一个动态系统库。这在编译要从另一种语言加载的动态库时使用。此输出类型将*.so在 Linux*.dylib上创建文件、在 macOS上创建文件以及*.dll在 Windows上创建文件。

我的 WASM 不是*.dylib, *.dll, 或*.so... 那么为什么必须将 crate 类型设置为 cdylib?幕后到底发生了什么?

库文件

#[no_mangle]
pub extern fn add_one(x: u32) -> u32 {
    x + 1
}
Run Code Online (Sandbox Code Playgroud)

Cargo.toml

[package]
name = "utils"
version = "0.1.0"
authors = [""]
edition = "2018"

[dependencies]

[lib]
crate-type = ["cdylib"] // Why is this needed
Run Code Online (Sandbox Code Playgroud)

索引.html:

[package]
name = "utils"
version = "0.1.0"
authors = [""]
edition = "2018"

[dependencies]

[lib]
crate-type = ["cdylib"] // Why is this needed
Run Code Online (Sandbox Code Playgroud)

终端:

<!DOCTYPE html>
<html>
  <head>
    <script> 
      fetch("utils.gc.wasm")
        .then(response => response.arrayBuffer())
        .then(result => WebAssembly.instantiate(result))
        .then(wasmModule => {
          const result = wasmModule.instance.exports.add_one(2);
          const text = document.createTextNode(result);
          document.body.appendChild(text);
        });
    </script>
  <head>
  <body></body>
<html>
Run Code Online (Sandbox Code Playgroud)

Mar*_*ein 5

正如 Rust 参考所述:我们正在创建一个从另一种语言加载的动态库。那么为什么输出既不是.dll,.so也不是.dylib?那是因为我们没有为 Windows、Linux 或 MacOS 进行编译。我们正在为wasm32-unknown-unknown. 所以这里参考的唯一缺点是没有列出所有可能的平台及其动态库文件结尾。

我们需要一个动态库,因为动态库可以在运行时加载(通常由浏览器加载)。Rust 库必须静态链接才能使用。

关于幕后发生的事情的额外信息:

如果您调用wasm_bindgen宏,它将(除其他外)将函数的签名扩展为C函数。

#[wasm_bindgen]
pub fn my_function() 
Run Code Online (Sandbox Code Playgroud)
#[export_name = "my_function"]
pub extern "C" fn __wasm_bindgen_my_function()
Run Code Online (Sandbox Code Playgroud)

为什么是 C 函数?函数调用可能因语言而异。通过修改、调用堆栈上参数的顺序等。这称为 ABI。C具有定义和稳定的 ABI 的明显优势,这就是为什么它是外部函数接口的流行选择。