本篇只是一个总体的介绍,并不是对 bindgen 项目的完整讲解,也不是对 bindgen tutorial 的全面翻译。 具体,可查看示例:https://rust-lang.github.io/rust-bindgen/tutorial-0.html bindgen 还有另一种用法,它本身也提供一个命令行工具。 执行: cargo install bindgen 便可安装。 bindgen 为我们提供了各种修补之法(这才是精华)。 同时,bindgen 对 C 的 Union 和 Bitfields 的特性,也有对应的处理策略。这些在实际封装的过程中,可能会经常碰到。 bindgen 本身知识点,并不多。
本文我们将通过一个示例,讨论如何使用 bindgen 将 C 库中的函数公开给 Rust。 上一篇我们介绍了使用 bindgen 为 C 库创建 Rust FFI 绑定有两种方式:使用 bindgen 命令行和使用 build.rs。本文我们使用build.rs这种方式作为示例进行说明。 ]部分,这样就声明了对 bindgen的构建时依赖并使用了最新版本 v0.55.1,可随时通过 crates.io bindgen 页面获取最新的版本信息。 bindgen::Builder是bindgen的主要入口点,可让为生成的绑定配置各种选项。.header用来指定要生成绑定的头文件。. 具体可以参考:https://rust-lang.github.io/rust-bindgen/ 与此同时,直接使用bindgen生成的 Rust FFI 绑定函数,需要通过 unsafe 的方式访问
= "0.2"ewf.djmfzb.mobi2.4 实现斐波那契函数编辑src/lib.rs:rustuse wasm_bindgen::prelude::*;#[wasm_bindgen]pub fn 3.3 进阶优化:使用迭代而非递归Rust版本可以进一步优化:rust#[wasm_bindgen]pub fn fibonacci_iter(n: i32) -> i32 { let mut a 400msWasm迭代:~0.05ms第四部分:实际应用案例4.1 图像处理使用image crate处理图像:rustuse image::{ImageBuffer, Rgba};use wasm_bindgen gray.to_rgba8().to_vec()}4.2 加密算法实现SHA-256svx.ycmfzb.mobi哈希:rustuse sha2::{Sha256, Digest};use wasm_bindgen ::prelude::*;muy.ycmfzb.mobi#[wasm_bindgen]pub fn sha256(input: &str) -> String {ewf.ycmfzb.mobi let
Rust web 前端库/框架在所有前端库/框架的位置 从评测结果来看,wasm-bindgen 性能和 vanillajs 处于同一水平,甚至有几项已经超越。 虽然说,目前 wasm-bindgen 还处于初级阶段,但其总需要通过 web-sys 和 js-sys 与 JavaScript 交互。 所以除非前端技术有什么超级大的变革,否则 wasm-bindgen 最好的性能估计也就是总体和原生 vanillajs 总体持平吧。 具体来说,wasm-bindgen、stdweb 是 wasm 模块与 JavaScript 之间的高层次交互库。 所以 wasm-bindgen、stdweb 肯定是各项评测性能都胜出的。
wasm-bindgen wasm-bindgen 提供了 JS 和 Rust 类型之间的桥梁,它允许 JS 使用字符串调用 Rust API,或者使用 Rust 函数来捕获 JS 异常。 wasm-bindgen 的核心是促进 javascript 和 Rust 之间使用 wasm 进行通信。 ::prelude::*; #[wasm_bindgen] extern "C" { fn alert(s: &str); } #[wasm_bindgen] pub fn big_computation () { alert("这个是一个超级耗时的复杂计算逻辑"); } #[wasm_bindgen] pub fn welcome(name: &str) { alert(&format! run build:wasm && npm run build:bindgen && npx webpack", 然后我们执行 npm run build 就可以打包所有代码啦。
Wasm-bindgen比stdout更底层,它试图提供对JavaScript和Rust交互方式的完全控制。实际上,甚至有人在谈论使用wasm-bindgen重写stdweb,这将解决不兼容的问题。 因为wasm-bindgen是更轻量级的选项(该选项由Rust WebAssembly官方工作组正式开发),所以我们将重点讨论这个选项。 use wasm_bindgen::prelude::wasm_bindgen; // This attribute makes calling Rust from JavaScript possible / #[wasm_bindgen] // This is pretty plain Rust code. 幸运的是,wasm-bindgen不仅仅只是一个库,它还具有为我们创建一种“胶水”JavaScript的能力。
将其更改为以下内容: extern crate wasm_bindgen; use wasm_bindgen::prelude::*; // 导入 'window.alert' #[wasm_bindgen , name)); } 我们简单解释一下核心代码: extern crate wasm_bindgen;: 这一行声明了对wasm_bindgen库的依赖。 use wasm_bindgen::prelude::*;: 这一行导入了wasm_bindgen库的预导出(prelude)模块中的所有内容,以便在后续代码中使用。 在 Rust 中调用来自 JavaScript 的外部函数 #[wasm_bindgen] extern "C" { fn alert(s: &str); } #[wasm_bindgen]: 最后,让我们看看wasm-bindgen生成的其他文件。
Wasm-bindgen 提供 WebAssembly(wasm)模块和 JavaScript 之间的高级别交互。 使用 wasm-bindgen,JavaScript 和 WebAssembly 之前不仅可以通过整形和浮点型进行通信,还可以使用字符串、JavaScript 对象和类进行。 wasm-bindgen 的高级功能包括: 导入 JavaScript 结构、函数和对象以在 WebAssembly 中调用。开发人员可以调用结构中的方法和访问属性。 基于 ECMAScript 模块,wasm-bindgen 专注于 Rust,但其目的也是最终用于 C 和 C ++ 等语言。 但 Mozilla 称 wasm-bindgen 目前还不够稳定,暂时还无法扩展到其它语言。 Rust 社区的一大目标是让 Rust 成为 Web 语言。
use futures::channel::oneshot; use wasm_bindgen::prelude::*; use wasm_bindgen_futures::JsFuture; use 如 #[wasm_bindgen] 标记的函数可以被 JavaScript 调用。 use futures::channel::oneshot; use wasm_bindgen::prelude::*; use wasm_bindgen_futures::JsFuture; use let array = js_sys::Array::new(); array.push(&wasm_bindgen::module()); array.push(&wasm_bindgen wasm-bindgen/examples/dom.html [7] Parallel Raytracing: https://rustwasm.github.io/wasm-bindgen/examples
libclang 被 bindgen 用做前端,用来处理 C 代码。libclang 可以从 llvm 官方主页 下载预编译好的版本。 安装 bindgen 工具,bindgen 是一个自动将 C 接口转为 RustFFI 接口的库: cargo install --locked --version 0.56.0 bindgen 克隆最新的 Bindgen 是一个 Rust 官方的工具,用来自动化地从 C 函数中生成 Rust 的 FFI 绑定。内核中的 Rust 也使用该工具从原生的内核 C 接口中生成 Rust 的 FFI 绑定。 quiet_cmd_bindgen = BINDGEN $@ cmd_bindgen = \ $(BINDGEN) $< $(shell grep -v '^\#\|^$$' $(srctree ,bindgen) ABI Rust 相关的代码会单独从 rs 编译为 .o,生成的目标文件是标准的 ELF 文件。
工具 cargo install wasm-bindgen-cli # 安装wasm-opt优化工具 cargo install wasm-opt --locked 安装前端工具 为了开发完整的Web ::prelude::*; // 将函数暴露给JavaScript #[wasm_bindgen] pub fn fibonacci(n: u32) -> u64 { if n <= 1 { ); } #[wasm_bindgen] pub fn greet(name: &str) { alert(&format! ("Greeted: {}", name))); } // 处理JavaScript数组 #[wasm_bindgen] pub fn process_array(array: &[u32]) -> , program: web_sys::WebGlProgram, } #[wasm_bindgen] impl WebGLRenderer { #[wasm_bindgen(constructor
修改为以下内容(先不必在意代码) src/lib.rs extern crate wasm_bindgen; use wasm_bindgen::prelude::*; #[wasm_bindgen ] extern { pub fn alert(s: &str); } #[wasm_bindgen] pub fn greet(name: &str) { alert(&format , name)); } 接着在 Cargo.toml 文件中添加 wasm-bindgen 依赖,wasm-bindgen 来提供 JavaScript 和 Rust 类型之间的桥梁,允许 JavaScript [package] name = "hello-wasm" version = "0.1.0" [lib] crate-type = ["cdylib"] [dependencies] wasm-bindgen lib.rs extern crate wasm_bindgen; extern crate md5; use wasm_bindgen::prelude::*; use md5::{Digest,
函数调用 暴露函数给 JS 调用 如果是需要暴露在 JS 中调用的函数,我们只需要使用 wasm_bindgen 过程宏即可,一个最简单的例子: #[wasm_bindgen] pub fn get_version 调用 JS 的函数 我们可以在 Rust 层调用 js 几乎任意的函数,只需声明即可,例如调用 js 中的 console.log: #[wasm_bindgen] extern { #[wasm_bindgen // Rust: #[wasm_bindgen] pub fn set_dom_inner(dom: HtmlElement) { dom.set_inner_html("This is from 在 Rust 中使用 console 在 Rust 中使用 console 对象上的方法和使用任何 JS 对象的方法一样,实际上非常简单: #[wasm_bindgen] extern { #[wasm_bindgen (s: &str); #[wasm_bindgen(js_namespace = console)] pub fn warn(s: &str); #[wasm_bindgen(js_namespace
wasm-bindgen:用于生成Rust与JavaScript之间的桥接代码。wasm-pack:简化了WebAssembly模块的打包和发布流程。3. Rust与WebAssembly的兼容性:掌握Rust如何通过工具链生成WebAssembly模块,以及如何利用wasm-bindgen暴露Rust逻辑到JavaScript。 依赖,它允许Rust与JavaScript进行交互:[dependencies]wasm-bindgen = "0.2"4. 我们将定义一个简单的加法函数和减法函数,并通过wasm-bindgen暴露给JavaScript。 use wasm_bindgen::prelude::*;// 必须定义`#[wasm_bindgen]`宏来将Rust函数暴露给JavaScript#[wasm_bindgen]pub fn add(
crate-type=["cdylib","rlib"][dependencies]#2.wasm-bindgen:Rust与JS之间的“智能大桥”wasm-bindgen="0.2.92"#3.image 的核心函数:grayscale**`#[wasm_bindgen]`宏告诉Rust编译器:*“这个函数需要被JS调用,请`wasm-bindgen`为它生成胶水代码。” `JsValue`是一个“动态”类型,*`wasm-bindgen`会把它转换成一个JS`Error`对象。*这实现了健壮的、跨语言的错误处理。 wasm-bindgen生成的JS胶水代码。永远不应该手动修改它。wasm_image_processor.d.ts:TypeScript类型定义。 wasm-bindgen自动生成了类型,提供了“智能感知”体验。package.json:一个完整的package.json。
└── lib.rs 这里面最重要的就是 Cargo.toml 了,其中最关键的依赖如下: [lib] crate-type = ["cdylib"] [dependencies] wasm-bindgen = "0.2" yew = "0.10.0" cdylib 是用于配置构建 C interoperability(C FFI),wasm-bindgen 依赖是用于 WASM 模块和JavaScript 加载 WASM 以及 bind 的过程 mod app; use wasm_bindgen::prelude::*; #[wasm_bindgen] pub fn run_app() -> Result JsValue> { yew::start_app::<app::App>(); Ok(()) } 在需要导出 Rust 函数到 JavaScript 中,只需要在函数方法上注释 #[wasm_bindgen
在 Rust 中,#[wasm_bindgen] 是一个属性宏(attribute macro),用于与 wasm-bindgen 工具一起工作。 use wasm_bindgen::prelude::*; #[wasm_bindgen] pub fn greet(name: &str) -> String { format! use wasm_bindgen::prelude::*; #[wasm_bindgen] extern "C" { fn alert(s: &str); } #[wasm_bindgen] use wasm_bindgen::prelude::*; #[wasm_bindgen] extern "C" { type Document; #[wasm_bindgen(method 使用wasm-bindgen: cargo install wasm-bindgen-cli cargo build --target wasm32-unknown-unknown wasm-bindgen
因此笔者选择 trunk,安装其需要 wasm-bindgen-cli 工具 crate。 cargo install trunk wasm-bindgen-cli 依赖项 crate 我们目前仅是 yew 开发环境的初始配置,所以需要的依赖项 crate 仅为 yew 和 wasm-bindgen cargo add yew wasm-bindgen 此时,frontend-yew 项目中的 Cargo.toml 文件内容如下: [package] name = "frontend-yew" version and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html [dependencies] wasm-bindgen
libclang 被 bindgen 用做前端,用来处理 C 代码。libclang 可以从 llvm 官方主页 下载预编译好的版本。 安装 bindgen 工具,bindgen 是一个自动将 C 接口转为 RustFFI 接口的库: cargo install --locked --version 0.56.0 bindgen 克隆最新的 Bindgen 是一个 Rust 官方的工具,用来自动化地从 C 函数中生成 Rust 的 FFI 绑定。内核中的 Rust 也使用该工具从原生的内核 C 接口中生成 Rust 的 FFI 绑定。 quiet_cmd_bindgen = BINDGEN $@ cmd_bindgen = \ $(BINDGEN) $< $(shell grep -v '^\#\|^$$' $(srctree ,bindgen) ABI Rust 相关的代码会单独从 rs 编译为 .o,生成的目标文件是标准的 ELF 文件。
例如,如果没有 ssvmup 和 wasm-bindgen,你就无法使用字符串或数组。 注意,say() 函数使用 #[wasm_bindgen] 注解,使 ssvmup 可以生成必要的“管道”,以从 TypeScript 来调用它。 #[wasm_bindgen] pub fn say(s: &str) -> String { let r = String::from("hello "); return r + s; } Deno 请注意,它们每个都用 #[wasm_bindgen] 注解过了。 #[wasm_bindgen] pub fn obfusticate(s: String) -> String { (&s).chars().map(|c| { match c {