Rust to WebAssembly using js console.log All In One
Rust to WebAssembly using js console.log All In One
# build the package
$ wasm-pack build --target web
<!DOCTYPE html>
<html lang="zh-Hans">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<meta http-equiv="X-UA-Compatible" content="ie=edge">
<meta name="author" content="xgqfrms">
<meta name="generator" content="VS code">
<title>Rust to WebAssembly using js console.log All In One</title>
</head>
<body>
<header>
<h1>Rust to WebAssembly using js console.log All In One</h1>
</header>
<main>
<section>
<a href="https://www.cnblogs.com/xgqfrms/p/16685185.html">Rust to WebAssembly</a>
</section>
</main>
<footer>
<p>copyright© xgqfrms 2022</p>
</footer>
<script type="module">
import init, { greet } from "./pkg/rust_to_wasm_npm.js";
init().then(() => {
// greet("Rust to WebAssembly and run wasm in js 🚀");
console.log('greet =', greet);
greet("Rust to WebAssembly and run wasm in js 🚀");
// greet.log("Rust to WebAssembly and run wasm in js 🚀");
});
</script>
</body>
</html>
console.log ❌
// ✅ Cargo.toml 中 dependencies 配置后,无需再次手动导入外部包 external crate
// 导入外部包 external crate
// extern crate wasm_bindgen;
// 引入 wasm_bindgen::prelude 的全部模块 *
use wasm_bindgen::prelude::*;
// 使用 wasm-bindgen 在 Rust 与 JavaScript 之间通信
/*
wasm-pack 使用另一个工具 wasm-bindgen 来提供 JavaScript 和 Rust 类型之间的桥梁。
它允许 JavaScript 使用字符串调用 Rust API,或调用 Rust 函数来捕获 JavaScript 异常。
*/
// 从 Rust 调用 JavaScript 中的外部函数
// #[] => 属性, 修改下一条语句 extern; 即,告诉 rust 调用一些外部定义的函数, wasm-bindgen 知道如何找到这些函数
#[wasm_bindgen]
extern {
// 函数签名 (参数名:参数类型)
// pub fn alert(s: &str);
// let console_log = console.log;
// pub fn console_log(s: &str);
// pub fn console.log(s: &str);
pub fn console(s: &str);
}
// 生成 JavaScript 可以调用的 Rust 函数
// #[] => 属性, 修改下一条语句 fn; 即,这个 Rust 函数能够被 JavaScript 调用
// public => pub
#[wasm_bindgen]
pub fn greet(name: &str) {
// &format!, 字符串格式化,即字符串插值
// alert(&format!("Hello, {}!", name));
// console_log(&format!("Hello, {}!", name));
// console.log(&format!("Hello, {}!", name));
console(&format!("Hello, {}!", name));
}
alert
// ✅ Cargo.toml 中 dependencies 配置后,无需再次手动导入外部包 external crate
// 导入外部包 external crate
// extern crate wasm_bindgen;
// 引入 wasm_bindgen::prelude 的全部模块 *
use wasm_bindgen::prelude::*;
// 使用 wasm-bindgen 在 Rust 与 JavaScript 之间通信
/*
wasm-pack 使用另一个工具 wasm-bindgen 来提供 JavaScript 和 Rust 类型之间的桥梁。
它允许 JavaScript 使用字符串调用 Rust API,或调用 Rust 函数来捕获 JavaScript 异常。
*/
// 从 Rust 调用 JavaScript 中的外部函数
// #[] => 属性, 修改下一条语句 extern; 即,告诉 rust 调用一些外部定义的函数, wasm-bindgen 知道如何找到这些函数
#[wasm_bindgen]
extern {
// 函数签名 (参数名:参数类型)
pub fn alert(s: &str);
}
// 生成 JavaScript 可以调用的 Rust 函数
// #[] => 属性, 修改下一条语句 fn; 即,这个 Rust 函数能够被 JavaScript 调用
// public => pub
#[wasm_bindgen]
pub fn greet(name: &str) {
// &format!, 字符串格式化,即字符串插值
alert(&format!("Hello, {}!", name));
}
solutions
#![allow(unused_variables)]
fn main() {
use wasm_bindgen::prelude::*;
#[wasm_bindgen(start)]
pub fn run() {
bare_bones();
using_a_macro();
using_web_sys();
}
// First up let's take a look of binding `console.log` manually, without the
// help of `web_sys`. Here we're writing the `#[wasm_bindgen]` annotations
// manually ourselves, and the correctness of our program relies on the
// correctness of these annotations!
#[wasm_bindgen]
extern "C" {
// Use `js_namespace` here to bind `console.log(..)` instead of just
// `log(..)`
#[wasm_bindgen(js_namespace = console)]
fn log(s: &str);
// The `console.log` is quite polymorphic, so we can bind it with multiple
// signatures. Note that we need to use `js_name` to ensure we always call
// `log` in JS.
#[wasm_bindgen(js_namespace = console, js_name = log)]
fn log_u32(a: u32);
// Multiple arguments too!
#[wasm_bindgen(js_namespace = console, js_name = log)]
fn log_many(a: &str, b: &str);
}
fn bare_bones() {
log("Hello from Rust!");
log_u32(42);
log_many("Logging", "many values!");
}
// Next let's define a macro that's like `println!`, only it works for
// `console.log`. Note that `println!` doesn't actually work on the wasm target
// because the standard library currently just eats all output. To get
// `println!`-like behavior in your app you'll likely want a macro like this.
macro_rules! console_log {
// Note that this is using the `log` function imported above during
// `bare_bones`
($($t:tt)*) => (log(&format_args!($($t)*).to_string()))
}
fn using_a_macro() {
console_log!("Hello {}!", "world");
console_log!("Let's print some numbers...");
console_log!("1 + 3 = {}", 1 + 3);
}
// And finally, we don't even have to define the `log` function ourselves! The
// `web_sys` crate already has it defined for us.
fn using_web_sys() {
use web_sys::console;
console::log_1(&"Hello using web-sys".into());
let js: JsValue = 4.into();
console::log_2(&"Logging arbitrary values looks like".into(), &js);
}
}
https://rustwasm.github.io/wasm-bindgen/examples/console-log.html
#[wasm_bindgen]
extern "C" {
// Use `js_namespace` here to bind `console.log(..)` instead of just
// `log(..)`
#[wasm_bindgen(js_namespace = console)]
fn log(s: &str);
// The `console.log` is quite polymorphic, so we can bind it with multiple
// signatures. Note that we need to use `js_name` to ensure we always call
// `log` in JS.
#[wasm_bindgen(js_namespace = console, js_name = log)]
fn log_u32(a: u32);
// Multiple arguments too!
#[wasm_bindgen(js_namespace = console, js_name = log)]
fn log_many(a: &str, b: &str);
}
fn bare_bones() {
log("Hello from Rust!");
log_u32(42);
log_many("Logging", "many values!");
}
https://www.webassemblyman.com/rustwasm/how_to_log_to_the_console_in_rust_webassembly.html
use log::{error, info, warn};
use wasm_bindgen::prelude::*;
use wasm_bindgen_console_logger::DEFAULT_LOGGER;
#[wasm_bindgen]
pub fn start() {
log::set_logger(&DEFAULT_LOGGER).unwrap();
log::set_max_level(log::LevelFilter::Info);
error!("Error message");
warn!("Warning message");
info!("Informational message");
}
https://docs.rs/wasm-bindgen-console-logger/latest/wasm_bindgen_console_logger/
test ✅
js_namespace 和 js_name
#[wasm_bindgen]
extern "C" {
// Use `js_namespace` here to bind `console.log(..)` instead of just `log(..)`
// 自定义 js name ✅ js_namespace 和 js_name 必须是 js 中真实存在的 ✅
#[wasm_bindgen(js_namespace = console, js_name = log)]
// fn log(s: &str);
fn console_log(s: &str);
// The `console.log` is quite polymorphic, so we can bind it with multiple signatures.
// Note that we need to use `js_name` to ensure we always call `log` in JS.
#[wasm_bindgen(js_namespace = console, js_name = log)]
fn log_u32(a: u32);
// Multiple arguments too!
#[wasm_bindgen(js_namespace = console, js_name = log)]
fn log_strs(a: &str, b: &str);
}
#[wasm_bindgen]
pub fn greet(name: &str) {
// &format!, 字符串格式化,即字符串插值
let string: &str = &format!("Hello, {}!", name);
// log(string);
console_log("自定义 js name ✅ js_namespace 和 js_name 必须是 js 中真实存在的 ✅\n");
console_log(string);
}
#[wasm_bindgen]
pub fn greet_u32(num: u32) {
// &format!, 字符串格式化,即字符串插值
log_u32(num);
}
#[wasm_bindgen]
pub fn greet_strs(str1: &str, str2: &str) {
// &format!, 字符串格式化,即字符串插值
let string1: &str = &format!("Hello, {}!", str1);
let string2: &str = &format!("\nThis year is {}!", str2);
log_strs(string1, string2);
}
refs
https://developer.mozilla.org/en-US/docs/WebAssembly/Rust_to_wasm
©xgqfrms 2012-2020
www.cnblogs.com/xgqfrms 发布文章使用:只允许注册用户才可以访问!
原创文章,版权所有©️xgqfrms, 禁止转载 🈲️,侵权必究⚠️!
本文首发于博客园,作者:xgqfrms,原文链接:https://www.cnblogs.com/xgqfrms/p/16685185.html
未经授权禁止转载,违者必究!