javascript – 使用WebAssembly在Rust中尝试Hello World时的LinkError
内容导读
互联网集市收集整理的这篇技术教程文章主要介绍了javascript – 使用WebAssembly在Rust中尝试Hello World时的LinkError,小编现在分享给大家,供广大互联网技能从业者学习和参考。文章包含4435字,纯文字阅读大概需要7分钟。
内容图文
我正在尝试使用WebAssembly运行Rust生成的hello world程序,但是当我尝试加载程序时,我收到一条错误消息.
当我找到一些我发现的教程时,我能够让它运行,问题是他们使用Emscripten创建JavaScript和HTML来加载代码,但是这个JavaScript和HTML包含大量的样板和其他东西.我有点失落,而是想尝试得到一个非常简单的例子,我正在装载自己.
我运行以下代码来编译hello.wasm
echo 'fn main() { println!("Hello, Emscripten!"); }' > hello.rs
rustc --target=wasm32-unknown-emscripten hello.rs
为了加载hello.wasm,我从Mozilla WebAssembly文档中获取了示例并试图运行它.
var importObject = {
imports: {
imported_func: function(arg) {
console.log(arg);
}
}
};
fetch('hello.wasm').then(response =>
response.arrayBuffer()
).then(bytes =>
WebAssembly.instantiate(bytes, importObject)
).then(results => {
// Do something with the compiled results!
});
WebAssembly.instantiate崩溃:
LinkError: Import #0 module="env" error: module is not an object or function
我发现有关此错误的一些事情与缺少的东西有关,应该加载样板代码,但通过自动生成的HTML和JavaScript查看我无法确切知道它可能是什么.
解决方法:
摘要
您必须定义一组由WASM模块导入的函数和值.当WASM模块导入您未正确定义的内容时,会出现此链接器错误. Emscripten生成了一大堆JS代码,它定义了WASM模块所需的所有导入(在这种情况下这很简单,因为Emscripten本身也生成WASM模块).
现在,您要么使用Emscripten运行时(JS文件),要么自己必须做很多事情.
我会试着更详细地解释一下,请耐心等待:
装配和WASM
汇编是人类可读的机器代码形式(但这两个术语通常可以互换使用,因此我们也不会关心这篇文章,只是称它为汇编).装配是为机器/ CPU执行而设计的,因此非常简单.汇编基本上是一个指令列表,其中每个指令执行特定的微小事情.例如,存在添加两个数字,在不同地址执行指令等的指令.
值得注意的是缺少打印指令. print的某些功能是完全不同的抽象级别,并且比单个指令做得更多.另外,“印刷”是什么意思?我们希望我们的程序可以访问某种控制台.重复一个重要部分:WASM没有打印指令或类似的东西!
印刷之类的东西需要由环境提供.对于大多数程序和大多数计算机科学而言,这种环境只是操作系统.它管理“控制台”,它让你打印.但是,WASM程序的直接环境是浏览器!因此浏览器必须为您提供打印方式.
链接
链接是将来自不同模块/编译单元的导入和导出相互连接(“解析”)的过程.例如,在Rust中使用extern crates以及在C中编译多个.cpp文件时,必须进行链接.
当您实例化WASM模块时,它也是必要的,因为模块可能具有导入.在我们执行模块之前,需要解决这些导入.
那么你的模块有进口吗?我们来看一下!您可以使用工具wasm-dis(反汇编程序)将二进制wasm代码转换为或多或少可读的汇编代码:$wasm-dis hello.wasm> hello.wast.查看此文件,我们可以看到以下内容:
(import "env" "DYNAMICTOP_PTR" (global $import$0 i32))
(import "env" "STACKTOP" (global $import$1 i32))
(import "env" "STACK_MAX" (global $import$2 i32))
(import "env" "abort" (func $import$3 (param i32)))
...
(58 more)
即使不知道如何阅读这种wast格式,我们也可以做出合理的猜测,并假设你的模块确实导入了东西.我们应该知道,因为我们想要打印而且没有打印指令!
(你可能想知道为什么没有(导入“env”“print”……).我无法完全解释这个,但原因基本上是:它比那更复杂.Emscripten只使用一小部分重要的导入并使用这些导入来访问环境中的其他功能.)
与WASM(和Emscripten)联系
WASM中的链接由WebAssembly.instantiate() method完成.正如您在链接文档中看到的,此方法采用importObject.如果未在此对象中定义函数/值(每次导入WASM模块一个函数/值),则会导致WebAssembly.LinkError.说得通.
如果要实例化文件hello.wasm定义的WASM模块,则必须定义所有62个导入.这看起来真烦人吧?实际上,您并不是真的希望这样做:这就是Emscripten为您生成必要的JS代码的原因! Emscripten生成的WASM模块应该加载Emscripten生成的JS-loader!
在正常程序中打印?
值得一看的是在本机环境(操作系统)中运行的程序如何进行打印.它们当然也需要与环境(即操作系统)相关联,对吧?并不是的.
虽然Rust,C和C等编程语言有一个用于打印的标准库,但该标准库不是操作系统的一部分.它只是使用操作系统本身.最后,为了打印,使用系统调用. Syscalls使用CPU中断来调用操作系统的功能.这有一些优点(例如,您不需要将程序与操作系统链接),但也有一些重要的缺点(例如,它不是很快).
AFAIK,WASM无法实现这些类型的系统调用(至少截至目前).
不使用Emscripten
编译到WASM需要两件大事:
> WASM代码生成:您的编译器必须吐出WASM代码
>链接:因为它通常不止一个箱子,我们需要链接(如上所述)
Emscripten同时执行¹并且可以将代码生成与链接匹配,因为这两个部分都是由Emscripten完成的.还有替代品吗?
是!您正在寻找的是Rust的wasm32未知未知目标.此目标使用LLVM的WASM后端来执行代码生成.使用此目标,您可以在没有Emscripten的情况下完全生成小型WASM模块.更重要的是:你也可以自己编写JS-loader,因为你决定了你的进口,没有什么是神奇的添加.
要了解有关这个令人兴奋的主题的更多信息,我建议您访问hellorust.com.在该网站上,您可以找到有关如何设置构建环境的简单示例和说明.
¹Emscripten不直接生成WASM.它生成asm.js代码,然后将其转换为WASM.
内容总结
以上是互联网集市为您收集整理的javascript – 使用WebAssembly在Rust中尝试Hello World时的LinkError全部内容,希望文章能够帮你解决javascript – 使用WebAssembly在Rust中尝试Hello World时的LinkError所遇到的程序开发问题。 如果觉得互联网集市技术教程内容还不错,欢迎将互联网集市网站推荐给程序员好友。
内容备注
版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 gblab@vip.qq.com 举报,一经查实,本站将立刻删除。
内容手机端
扫描二维码推送至手机访问。