当前位置: 首页 > article >正文

WebAssembly (Wasm) 与 JavaScript 字符串交互

随着WebAssembly(简称Wasm)技术的发展,越来越多的Web应用开始利用Wasm来提高性能。Wasm是一种在现代Web浏览器中运行的二进制格式,可以提供接近原生代码的速度。然而,Wasm和JavaScript之间进行数据交换时需要特别注意,尤其是对于字符串这种复杂类型的数据。

基础知识

在Wasm中,内存是通过线性内存(Linear Memory)来管理的,它是一个连续的字节数组。由于Wasm本身没有字符串类型,因此字符串必须以某种方式编码为字节序列后才能存储在线性内存中。通常,我们使用UTF-8编码来表示字符串。

JavaScript与Wasm之间的字符串交互涉及以下几个关键步骤:

  1. 从JS向Wasm传递字符串:将字符串转换为UTF-8编码,并将其写入Wasm的线性内存中。
  2. Wasm处理字符串:在Wasm中读取并处理这些字符串。
  3. 从Wasm向JS返回字符串:将处理后的字符串从线性内存中读出,并转换回JavaScript中的字符串。
示例代码

下面我们将通过一个简单的例子来演示如何实现上述过程。假设我们有一个Wasm模块,该模块包含一个函数to_uppercase,它可以接收一个字符串参数,对其进行某些处理(例如转换成大写),然后返回处理后的字符串。

Wasm 模块 (example.wasm)

首先,我们需要编写一个简单的Wasm模块。这里使用C语言作为示例:

#include <emscripten.h>
#include <string>
#include <cstring>

extern "C" {

EM_PORT_API const char* to_uppercase(const char* input) {
    std::string output = input;
    for (char &c : output) {
        c = toupper(c); // 转换为大写
    }

    // 为输出字符串分配内存
    char* result = (char*)malloc(output.size() + 1);
    strcpy(result, output.c_str());
    return result; // 返回大写字符串
}

EM_PORT_API void free_string(const char* str) {
    free((void*)str); // 释放分配的内存
}

}

编译上述C代码为Wasm模块(使用emcc命令):

emcc string.cpp -o string.js -s MODULARIZE=1 -s EXPORT_NAME="createModule" -s "EXPORTED_FUNCTIONS=['_to_uppercase', '_free_string','UTF8ToString','allocateUTF8']" -s "EXTRA_EXPORTED_RUNTIME_METHODS=['ccall', 'cwrap']"

EXPORTED_FUNCTIONS里面是Wasm对js开放的函数,写在c里面用_做前缀导出,非c的,js的就是原来的样子,这类非c的函数有哪些可以在生成的string.js里面看,根据需要导出
举例:‘allocateUTF8’,‘UTF8ToString’,‘getValue’,‘intArrayFromString’,‘intArrayToString’,‘UTF8ArrayToString’,‘stringToUTF8Array’,‘stringToUTF8’,‘allocate’,‘ALLOC_NORMAL’
这将生成两个文件:string.jsstring.wasm。其中,string.js 是一个加载器,用于帮助加载和初始化Wasm模块。

JavaScript 调用

接下来,在JavaScript中调用这个Wasm函数:

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>WebAssembly String Processing</title>
    <script src="string.js"></script>
</head>
<body>
    <h1>WebAssembly String Processing</h1>
    <input type="text" id="inputString" placeholder="Enter string">
    <button id="convertButton">Convert to Uppercase</button>
    <p id="result"></p>

    <script>
        let moduleInstance;

        createModule().then(instance => {
            moduleInstance = instance;

            document.getElementById('convertButton').onclick = () => {
                const inputString = document.getElementById('inputString').value;

                // 调用 C++ 函数
                const upperPtr = moduleInstance._to_uppercase(moduleInstance.allocateUTF8(inputString));
                const upperString = moduleInstance.UTF8ToString(upperPtr);

                document.getElementById('result').innerText = `Uppercase: ${upperString}`;

                // 释放分配的内存
                moduleInstance._free_string(upperPtr);
            };
        });
    </script>
</body>
</html>

在这个例子中,我们使用了allocateUTF8UTF8ToString这两个辅助函数。allocateUTF8是将js字符串分配好空间,变成c的char指针,给到wasm访问,UTF8ToString则是将wasm的char指针变成js能用字符串。记住,wasm跟js的实际通讯只有数字,int,char这些。

总结

通过以上示例,我们可以看到在Wasm和JavaScript之间传递字符串并不是一件直接的事情,需要经过编码、解码以及内存管理的过程。不过,借助于Emscripten提供的工具和API,这一过程可以变得更加简单和高效。

希望这篇文章能帮助你更好地理解Wasm与JavaScript之间的字符串交互机制。如果你有任何疑问或建议,欢迎留言交流!


http://www.kler.cn/news/318193.html

相关文章:

  • shardingjdbc分库分表原理
  • 实战16-RVP定义完成适配
  • rocky9.2的lvs的NAT模式下的基本使用的详细示例
  • SpringBoot使用@Async注解,实现异步任务
  • 002.k8s(Kubernetes)一小时快速入门(先看docker30分钟)
  • WPF经典面试题全集
  • JavaEE: 深入探索TCP网络编程的奇妙世界(一)
  • 【MySQL】数据类型【mysql当中各自经典的数据类型的学习和使用】
  • Leetcode 136 只出现一次的数字
  • EfficientFormer实战:使用EfficientFormerV2实现图像分类任务(一)
  • WPF 的TreeView的TreeViewItem下动态生成TreeViewItem
  • 合宙LuatOS应用,与时间相关那些事
  • k8s中pod的创建过程和阶段状态
  • Allegro视频去除走线的小方块
  • Milvus - 四种一致性级别与应用场景解析
  • 可靠传输是什么?是基于UDP实现的吗
  • JUC并发编程_四大函数式接口和 Stream 流式计算
  • 适用于 Windows 的 7 大数据恢复工具,可靠的数据恢复工具可有效地恢复丢失的文件
  • 后端开发工程师转行大模型领域:全面学习路线指南,非常详细收藏我这一篇就够了
  • 【大语言模型_1】VLLM部署Qwen模型
  • 【速成Redis】04 Redis 概念扫盲:事务、持久化、主从复制、哨兵模式
  • 2-102基于matlab的蒙特卡洛仿真
  • C语言——文件操作
  • [数据结构]动态顺序表的实现与应用
  • 第二证券:“产业+科技” 中国并购重组市场持续升温
  • 【微服务即时通讯系统】——etcd一致性键值存储系统,etcd的介绍,etcd的安装,etcd使用和功能测试
  • Scikit-learn 识别手写数字
  • Qt:NULL与nullptr的区别(手写nullptr)
  • 数据处理与统计分析篇-day10-Matplotlib数据可视化
  • Leetcode 每日一题:Diameter of Binary Tree