c语言部分

如果功能比较简单,可以直接使用WasmFiddlec/c++ 编译成 wasm。这个示例比较简单,先声明一个全局数组变量,由 js 写入和读取该变量。wasm 不仅可以导出函数,也可以从js导入函数,也就是在js实现由c/c++声明的 extern 函数。

// 定义待排序数组的大小
#define N 10

// 定义全局数组,在模块初始化时就在内存分配
int array[N];

// 定义js需要实现的函数,主要用来打印数组
extern void print(int* arr, int length);

// js获取数组
int* getArray() {
  return array;
}

获取数组指针,主要是定位该数组在线性内存的起始位置,再结合偏移量大小,这是在 js 读写这内存区域的关键。

小程序部分


  // 将数组写到类型数组
  importArrayToBuffer(memory, arr, offset) {
    const buffer = new Uint32Array(memory.buffer, offset, arr.length);
    for(let i = 0; i < arr.length; i++) {
      buffer[i] = arr[i];
    }
  },
  loadWasm() {
    WXWebAssembly.instantiate("/wasm/sort.wasm", {
      env: {
        print: (offset, length) => {
          // 排序后会执行此方法,这里读取内存并打印
          const buffer = new Uint32Array(this.pageData.memory.buffer, offset, length);
          // js的类型数组,看起来像普通的数组,但它其实是一个对象
          this.setData({
            after: JSON.stringify(Object.values(buffer)),
          })
        }
      }
    }).then(res => {
      this.pageData.exports = res.instance.exports;
      this.pageData.memory = this.pageData.exports.memory;
      this.sort();
    })
  },

在实例化 wasm 模块时,需要将 print 函数先实现了,否则会报错。实例化成功后,会有一个 memory 属性,这是获取线性内存的关键。Uint32Array 构造函数中,第一个参数是线性内存的对象,第二个参数是数组的起始位置,第三个参数是数组的长度。

总结

如果对WebAssembly有兴趣的同学可以下载源码学习一下,目前网上实战的案例比较少,我也是刚入手不久,需要通过不断练习才能熟练使用。WebAssembly与区块链技术结合起来,相信未来这块应用会越来越多,可以赋予浏览器、移动设备更多的功能。 需要源码的可以关注【技不离身】,回复 1001 可以获取下载地址。