将调用C ++的Rust编译为WASM

5
我发现了这篇文章 How do I use a C library in a Rust library compiled to WebAssembly?,但它依赖于已经停止更新的 wasm-merge(详情请参考 此链接)。我的问题是:我有一些 C++ 代码,我想从 Rust 中调用这些代码,以便可以编译出结果包,用于移动应用程序中的本地代码,或者编译为 WebAssembly,用于在 Node.js 中使用。目前,我的设置如下:

libTest.cpp

extern "C"{
    int test_function(int i){
        return i;
    }
}

lib.rs

use wasm_bindgen::prelude::*;

#[link(name = "Test")]
extern "C"{
    pub fn test_function(i: i32) -> i32 ;
}

#[wasm_bindgen]
pub fn test_function_js(i : i32) -> i32{
    let res = unsafe{test_function(i)};
    res
}    

build.rs

fn main() {
    cc::Build::new()
        .cpp(true)
        .file("libTest.cpp")
        .compile("libTest.a");
}

使用简单的cargo build编译成本机代码可以编译并工作,但用于wasm构建时不起作用,我正在使用cargo build --target wasm32-unknown-unknown进行构建。在那里我遇到了两个错误。

  = note: rust-lld: error: /[path to my project]/target/wasm32-unknown-unknown/debug/build/rustCpp-cc5e129d4ee03598/out/libTest.a: archive has no index; run ranlib to add one
          rust-lld: error: unable to find library -lstdc++

这样做是正确的吗?如果是,我该如何解决上述错误?如果不是,我该如何最好地从Rust调用C++并将其编译为wasm?

1个回答

2
(这并不是完整的答案,但对于评论来说太长了。)
我可以使用以下命令编译您的示例:
cc::Build::new()
  .archiver("llvm-ar") // Takes care of "archive has no index" - emar might be an alternative
  .cpp_link_stdlib(None) // Takes care of "unable to find library -lstdc++"// rest of your flags

但我不确定生成的二进制文件是否对您有用。特别是在调试模式下编译时,它包含WASI导入项,如果您开始使用任何有趣的函数(例如sin),可能会出现链接器错误。

理论上,您可以通过.flag("--sysroot=/usr/share/wasi-sysroot/")(如果已安装wasi-sdk或wasi-libc ++)为C ++编译器提供完整的stdlib,但是

  • 我不确定如何最好地解决此文件夹通常安装在哪里的差异(可能像这样
  • 我认为您还必须在链接时传递此标志,但我不知道如何传递(尽管似乎没有也可以正常工作)
  • 那将针对wasi,并且可能对您考虑的任何基于bindgen的环境没有用处。

嗨,我正在做类似于 OP 的事情。尝试在 Rust 中使用 WASI 的 C 库。你有什么建议吗?https://dev59.com/NcXsa4cB1Zd3GeqPSyKm - Kival M
1
虽然还没有完全达到目标,但这绝对是朝着正确方向迈出的一步,值得点赞,谢谢 Caesar!另外,对于其他读者来说,使用 emar 而不是 llvm-ar 实际上可以摆脱所有 wasi 依赖,非常方便。 - user8352734

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接