xgqfrms™, xgqfrms® : xgqfrms's offical website of cnblogs! xgqfrms™, xgqfrms® : xgqfrms's offical website of GitHub!

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&copy; 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://stackoverflow.com/questions/66836479/calling-console-log-from-rust-wasm32-wasi-without-the-need-for-ssvm-ssvmup

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, 禁止转载 🈲️,侵权必究⚠️!


posted @ 2022-09-12 17:07  xgqfrms  阅读(102)  评论(3编辑  收藏  举报