golang 调用rust
在为什么要在WebAssembly中使用Rust? ,我探讨了为什么您可能要编写WebAssembly(Wasm),以及为什么您可能会选择Rust作为语言来编写。现在,我将通过探索将Rust嵌入JavaScript的方式来分享它的外观。
这是将Rust与Go,C#和其他语言(具有可编译为Wasm的大型运行时)区分开来的功能。 Rust的运行时最少(基本上只是一个分配器),可以轻松地从JavaScript库使用Rust。 C和C ++有相似的故事,但是Rust的独特之处在于它的工具,我们现在来看一下。
基础
如果您以前从未使用过Rust,那么您首先需要进行设置。 很简单 首先下载Rustup ,这是一种控制Rust版本和不同工具链进行交叉编译的方式。 这将使您可以访问Cargo ,这是Rust构建工具和包管理器。
现在我们要做出决定。 我们可以很容易地编写通过WebAssembly在浏览器中运行的Rust代码,但是如果我们要做的事情除了使人们的CPU迷们旋转之外,我们可能会在某个时候想与文档对象模型(DOM)进行交互或使用一些JavaScript API。 换句话说: 我们需要JavaScript互操作 (又称JavaScript互操作性API)。
问题与解决方案
好消息是,有两个库可以促进基于Rust的Wasm与JavaScript之间的通信: wasm-bindgen和stdweb 。 不幸的是,不幸的是,这两个库彼此不兼容。 wasm-bindgen比stdweb低,并且尝试提供对JavaScript和Rust交互方式的完全控制。 事实上,还有的甚至通话使用WASM-BindGen自重写stdweb ,这将摆脱不兼容的问题。
由于wasm-bindgen是重量较轻的选项(该选项由Rust WebAssembly官方工作组正式开发),因此我们将重点介绍该选项。
wasm-bindgen和wasm-pack
我们将创建一个函数,该函数从JavaScript中获取字符串,将其变为大写并在其前面加上“ HELLO”,然后将其返回给JavaScript。 我们称这个函数为“ 激动的问候” !
首先,让我们创建一个Rust库,其中将包含这个出色的功能:
$ cargo new my
- wasm
- library
-- lib
$ cd my
- wasm
- library
现在,我们要用令人兴奋的逻辑替换src / lib.rs的内容。 我认为最好写出代码而不是复制/粘贴。
// Include the `wasm_bindgen` attribute into the current namespace.
use wasm_bindgen::prelude::wasm_bindgen;
// This attribute makes calling Rust from JavaScript possible.
// It generates code that can convert the basic types wasm understands
// (integers and floats) into more complex types like strings and
// vice versa. If you're interested in how this works, check this out:
// https://blog.ryanlevick.com/posts/wasm-bindgen-interop/
#[wasm_bindgen]
// This is pretty plain Rust code. If you've written Rust before this
// should look extremely familiar. If not, why wait?! Check this out:
// https://doc.rust-lang.org/book/
pub fn excited_greeting(original: &str) -> String {
format!("HELLO, {}", original.to_uppercase())
}
其次,我们必须对Cargo.toml配置文件进行两项更改:
- 添加wasm_bindgen作为依赖项。
- 将库二进制文件的类型配置为cdylib或动态系统库。 在这种情况下,我们的系统是wasm ,设置此选项是我们产生.wasm二进制文件的方式。
[ package
]
name
=
"my-wasm-library"
version
=
"0.1.0"
authors
=
[
"$YOUR_INFO"
]
edition
=
"2018"
[ lib
]
crate
-
type
=
[
"cdylib"
,
"rlib"
]
[ dependencies
]
wasm
- bindgen
=
"0.2.33"
现在开始构建! 如果仅使用cargo build ,我们将获得一个.wasm二进制文件,但是为了使从JavaScript调用Rust代码更容易,我们希望有一些JavaScript代码可以将丰富JavaScript类型(例如字符串和对象)转换为指针,并代表我们将这些指针传递给Wasm模块。 手动执行此操作很繁琐且容易出现错误。
幸运的是,除了是一个库之外, wasm-bindgen还具有为我们创建此“胶水” JavaScript的能力。 这意味着在我们的代码中,我们可以使用普通JavaScript类型与Wasm模块进行交互,并且wasm-bindgen生成的代码将完成将这些丰富的类型转换为Wasm真正理解的指针类型的工作。
我们可以使用很棒的wasm-pack来构建Wasm二进制文件,调用wasm-bindgen CLI工具,并将所有JavaScript(以及任何可选的生成的TypeScript类型)打包到一个简洁的程序包中。 现在就开始吧!
首先,我们需要安装wasm-pack :
$ cargo install wasm - pack
默认情况下, wasm-bindgen生产ES6模块。 我们将使用来自简单脚本标签的代码,因此我们只希望它产生一个普通的旧JavaScript对象,使我们可以访问Wasm函数。 为此,我们将--target no-modules选项传递给它。
$ wasm - pack build -- target no - modules
现在,我们的项目中有一个pkg目录。 如果我们查看内容,将会看到以下内容:
- package.json :如果我们要将其打包为NPM模块,则很有用
- my_wasm_library_bg.wasm :我们实际的Wasm代码
- my_wasm_library.js :JavaScript“胶水”代码
- 一些TypeScript定义文件
现在,我们可以创建一个index.html文件,该文件将使用我们JavaScript和Wasm:
< html >
< head >
< meta content = "text/html;charset=utf-8" http-equiv = "Content-Type" / >
< / head >
< body >
<!-- Include our glue code -->
< script src = './pkg/my_wasm_library.js' >< / script >
<!-- Include our glue code -->
< script >
window.addEventListener('load', async () => {
// Load the wasm file
await wasm_bindgen('./pkg/my_wasm_library_bg.wasm');
// Once it's loaded the `wasm_bindgen` object is populated
// with the functions defined in our Rust code
const greeting = wasm_bindgen.excited_greeting("Ryan")
console.log(greeting)
});
< / script >
< / body >
< / html >
您可能会想在浏览器中打开HTML文件,但是不幸的是,这是不可能的。 出于安全原因,必须从与HTML文件相同的域中提供Wasm文件。 您将需要一个HTTP服务器。 如果您有喜欢的静态HTTP服务器,可以从文件系统提供文件,请随时使用。 我喜欢使用basic-http-server ,您可以像这样安装和运行它:
$ cargo install basic
- http
- server
$ basic
- http
- server
现在,通过转到http:// localhost:4000 / index.html并通过Web服务器打开index.html文件,并检查您JavaScript控制台。 您应该在那里看到一个非常令人兴奋的问候!
如有任何疑问,请告诉我 。 下次,我们将研究如何在Rust代码中使用各种浏览器和JavaScript API。
翻译自: https://opensource.com/article/19/3/calling-rust-javascript
golang 调用rust