• WebAssembly学习笔记(一)


    WebAssembly学习笔记(一)

    编译和导入wasm模块

    用Emscripten编译C/C++并使用HTML模板

    让Emscripten生成WebAssembly模块、JavaScript plubming文件, 以及HTML模板文件。

    [外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-LK77Cj5N-1670298706899)(/img/webassembly/0101.png)]

    • 创建一个用于存放文件的目录: WebAssembly\Chapter 3\3.4 html_template\。

    • 创建C或C++代码。

      • 创建一个名为 calculate_primes.c 的文件。要做的第一件事是包含C标准库、 C标准输入和输出,以及Emscripten库的头文件。

      • #include <stdlib.h>

        #include

        #include

    • 将C代码编译为WebAssembly模块。

      • 进入目录WebAssembly\Chapter 3\3.4 html_template\,打开一个控制台窗口,然后定位到这个目录。
      • 运行以下命令可以生成WebAssembly模块、JavaScript plumbing文件和一个HTML模板。
        • emcc calculate_primes.c -o html_template.html
    • 在Web浏览器中打开HTML文件查看结果。

      • Emscripten创建的HTML文件会将任何来自模块的printf输出定向到一个文本框,这样不需要打开浏览器开发者工具,就可以在页面上看到输出。

    用Emscripten生成JavaScript plumbing代码

    让Emscripten生成WebAssembly模块和JavaScript plumbing文件。修改一个HTML文件或者创建一个新文件,以引用生成的 JavaScript文件。

    [外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-rOC1UpCs-1670298706900)(/img/webassembly/0102.png)]

    • 创建一个用于存放文件的目录: WebAssembly\Chapter 3\3.5 js_plumbing\ 。

    • 创建C或C++代码。

    • 将C代码编译为WebAssembly模块。

      • 进入目录 WebAssembly\Chapter 3\3.5 js_plumbing\,打开一个控制台窗口,然后定位到这个目录。

      • 运行以下命令,让Emscripten创建WebAssembly 模块和JavaScript文件。

        • emcc calculate_primes.c -o js_plumbing.js

    • 修改一个HTML文件或者创建一个新文件,以引用生成的 JavaScript文件。

      • ←---- 这个JavaScript文件会处理WebAssembly模块的加载和实例化
    • 在Web浏览器中打开HTML文件查看结果。

    用Emscripten只生成WebAssembly文件

    让Emscripten只生成WebAssembly模块。 然后创建必要的 HTML和JavaScript代码,以下载和实例化模块。

    [外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-Ar1LanN8-1670298706900)(/img/webassembly/0103.png)]

    • 创建一个用于存放文件的目录:WebAssembly\Chapter 3\3.6 side_module\。

    • 是创建C/C++代码。

    • 让Emscripten只生成WebAssembly文件。

      • 含优化标记-O1,如果没有指定优化标记,则Emscripten会使用默认的-O0(大写字母O和数字0),这表示不执行任何优化。

      • 需要将函数Increment指定为导出函数,这样它才能够被JavaScript代码调用。为了向Emscripten编译器指示这一点,可以在命令行参数-s EXPORTED_FUNCTIONS中包含这个函数名。生成WebAssembly文件时, Emscripten会在这个函数前添加一个下划线字符,因此将函数名包含到导 出数组时,需要包含下划线字符:_Increment。

      • emcc side_module.c -s SIDE_MODULE=2 -O1

        ➥ -s EXPORTED_FUNCTIONS=[‘_Increment’] -o side_module.wasm

    • 创建一个HTML文件并编写JavaScript代码从服务器请求这个文件,并让这个模块完成实例化。

      • promise与箭头函数表达式

      • JavaScript对象简写

      • WebAssembly JavaScript API概览

      • 编写JavaScript代码来获取并实例化模块

        • 定义一个JavaScript对象,将其命名为importObject,它有一个名为env的子对象,其中包含一个memory_base属性,这是这个模块想要导入的。这个memory_base属性会简单持有一个0值,因为我们不会动态链接这个模块。

        • 创建好importObject后,就可以调用函数instantiateStreaming,传入Wasm文件的fetch方法的结果作为第一个参数,importObject作为第二个参数。

        • instantiateStreaming会返回一个promise,因此我们将设置一个处理函数作为成功回调,模块完成下载、编译并实例化后,它就会被调用。此时可以访问这个WebAssembly模块实例的导出元素并调用_Increment函数。

        • const importObject = {
               env: {
                   __memory_base: 0,
               }
          };
          WebAssembly.instantiateStreaming(fetch("side_module.wasm"),
          ➥ importObject).then(result => {
               const value = result.instance.exports._Increment(17);
               console.log(value.toString());
          });
          
          • 1
          • 2
          • 3
          • 4
          • 5
          • 6
          • 7
          • 8
          • 9
          • 10
      • 创建一个基本的HTML页面

        •  <script>
               const importObject = {
                   env: {
                       __memory_base: 0,
                   }
               };
               WebAssembly.instantiateStreaming(fetch("side_module.wasm"),
                   ➥ importObject).then(result => {
                       const value = result.instance.exports._Increment(17);
                       console.log(value.toString());
               });
           script>
          
          • 1
          • 2
          • 3
          • 4
          • 5
          • 6
          • 7
          • 8
          • 9
          • 10
          • 11
          • 12

    使用wasm模块中的函数

    用C/C++创建带Emscripten plumbing的模块

    • 修改C++代码。

      • Emscripten的条件编译符号与头文件

        • Emscripten提供了条件编译符号__EMSCRIPTEN__,你可以用其检测正在编译这个解决方案的是否为Emscripten。

        • #include

          #include

          #ifdef EMSCRIPTEN ←---- 当代码被Emscripten编译时这个符号存在

          ​ #include ←---- Emscripten库的头文件

          #endif

      • extern "C"块

        • 在C++中,函数名可以被重载(overload),因此,编译时为了确保名称的唯一性,编译器会通过添加与函数参数相关的信息来改变它。编译代码时,编译器会修改函数名,这对于想要调用某个特定函数的外部代码来说是一个问题,因为那个函数名已经不复存在了。

        • 需要为函数包裹一个extern "C"块。将来要添加到这个文件中的所有函数都会放在这个块内。

        • #ifdef __cplusplus

          extern “C” { ←---- 因此编译器不会在这对大括号内重命名函数

          #endif

          ​ ←---- WebAssembly函数将放在这里

          #ifdef __cplusplus

          }

          #endif

    • 将代码编译为WebAssembly模块。

      • 在编写与模块交互的JavaScript代码时,将使用到Emscripten辅助函数ccall和UTF8ToString。

      • emcc validate.cpp -o validate.js

        ➥ -s EXTRA_EXPORTED_RUNTIME_METHODS=[‘ccall’,‘UTF8ToString’]

      • 辅助函数ccall:帮助调用模块函数,并在字符串希望只在调用期间存在时,辅助管理这些字符串的内 存。

      • 辅助函数UTF8ToString:这个函数接受一个指针,并从这个内存位置读取字符串。

    • 创建网页。

    • 创建与模块交互的JavaScript代码。

      • 将生成的文件复制到HTML文件所在目录,然后创建JavaScript代码与模块交互。

    用C/C++创建不使用Emscripten的模块

    [外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-abg5HYV5-1670298706900)(/img/webassembly/0105.png)]

    js和wasm的数据交互

    // 没有更完,先鸽一下

    更多内容在【倦倦喵.cn】~

  • 相关阅读:
    小白学java
    Qt实现控件的折叠收起和展开的功能
    005 数据结构
    美女放电还是整形-从《人月神话》误译谈状态机图
    像你这么优秀的测试工程师,怎么就约不到面试呢?
    【CKA考试笔记】二十、升级k8s
    6. 抽象类和接口
    针对微电网中可时移,柔性,基础负荷的电价响应模型---代码解析
    Linux入门——基础指令
    文本语音互相转换系统设计
  • 原文地址:https://blog.csdn.net/qq_42467009/article/details/128200449