美文网首页
通过WasmFiddle平台构建WASM模块

通过WasmFiddle平台构建WASM模块

作者: 盼旺 | 来源:发表于2019-12-10 12:17 被阅读0次

    1.WasmFiddle在线平台网址

    https://wasdk.github.io/WasmFiddle/

    2.编写C++源代码

    #define N 10
    //定义将从javascript环境导入的函数
    extern void print(int* offset,int length);
    //声明用于排序的全局数组,在模块初始化时就已在内存中生成
    int array[N];
    //用于在js环境中获取待排数组首地址的方法
    int* getArrayOffset(){
      return array;
    }
    //交换函数
    void swap(int *a,int *b){
      int temp;
      temp=*a;
      *a=*b;
      *b=temp;
      return;
    }
    //核心快排
    void quicksort_core(int array[],int maxlen,int begin,int end){
      int i,j;
      if(begin<end){
        i=begin+1;
        j=end;
        while(i<j){
          if(array[i]>array[begin]){
            swap(&array[i],&array[j]);
            j--;
          }else{
            i++;
          }
        }
        if(array[i]>=array[begin]){
          i--;
        }
        swap(&array[begin],&array[i]);
        quicksort_core(array,maxlen,begin,i);
        quicksort_core(array,maxlen,j,end);
      }
    }
    //用于在js环境中调用的主排序的方法
    void sort(){
      quicksort_core(array,N,0,N-1);
    //调用从js环境导入的“打印”方法
      print(array,N);
    }
    

    extern是计算机语言中的一个关键字,可置于变量或者函数前,以表示变量或者函数的定义在别的文件中。

    3.点击Build启动编译

    4.下载Wasm模块

    5.编写html代码

    <!DOCTYPE html>
    <html lang="en">
    <head>
        <meta charset="UTF-8">
        <title>我的第一个WASM应用</title>
    </head>
    
    <body>
    <p><span>排序前:</span><span class="sequence-before"></span></p>
    <p><span>排序后:</span><span class="sequence-after"></span></p>
    <script>
    //该方法用于从js环境向指定的共享堆内存段填充数据
    function importArrayToBuffer(memory,array,offset) {
        const importBuffer = new Uint32Array(memory.buffer,offset,array.length);
        for(let i=0;i<array.length;i++){
            importBuffer[i] = array[i];
        }
    }
    //从远程加载一个WASM的模块,并将该模块中的内容转换成二进制数据
    let startTime = performance.now();
    fetch("/cctest/original.wasm").then(response => response.arrayBuffer()).then((bytes) =>{
        let memory;
    //通过浏览器提供的标准WebAssembly接口来编译和初始化一个Wasm模块
        WebAssembly.compile(bytes).then(module => WebAssembly.instantiate(module,{
            env:{
                print (offset,len){
                    let strBuffer = new Uint32Array(memory.buffer,offset,len);
                    document.querySelector('.sequence-after').innerText=JSON.stringify(Object.values(strBuffer));
                }
            }
        })).then(instance =>{
    //输出下载,编译及实例化模块花费的时间
            console.log(performance.now()-startTime);
    //取出从Wasm模块中导出的函数
            let exports = instance.exports;
    //wasm实例所有信息
            console.log("实例的所有信息");
            console.log(exports);
    //获取该Wasm模块实例使用的堆内存对象
            memory=exports.memory;
            let arr =[];
            for(let i=0;i<10;i++){
                arr.push(Math.round(Math.random()*10));
            }
            document.querySelector('.sequence-before').innerText=JSON.stringify(arr);
    //将整型数组内的元素依次填充到指定的内存段,即填充到Wasm模块初始化时生成的数组中
            importArrayToBuffer(memory,arr,exports.getArrayOffset());
    //调用Wasm模块暴露的排序函数
            exports.sort();
        });
    });
    </script>
    </body>
    </html>
    

    6.在IDEA中构建一个Web应用然后启动

    推荐js方法二

    利用WebAssembly.instantiateStreaming()方法,可直接从系统底层的数据流源来编译并实例化一个Wasm模块

    <!DOCTYPE html>
    <html lang="en">
    <head>
        <meta charset="UTF-8">
        <title>我的第一个WASM应用</title>
    </head>
    
    <body>
    <p><span>排序前:</span><span class="sequence-before"></span></p>
    <p><span>排序后:</span><span class="sequence-after"></span></p>
    <script>
    function importArrayToBuffer(memory,array,offset) {
        const importBuffer = new Uint32Array(memory.buffer,offset,array.length);
        for(let i=0;i<array.length;i++){
            importBuffer[i] = array[i];
        }
    }
    let startTime = performance.now();
    WebAssembly.instantiateStreaming(fetch("/cctest/original.wasm"),{
        env:{
             print (offset,len){
               let strBuffer = new Uint32Array(memory.buffer,offset,len);
               console.log(strBuffer);
               document.querySelector('.sequence-after').innerText=JSON.stringify(Object.values(strBuffer));
             }
        }
    }).then(resultObject =>{
        console.log(performance.now()-startTime);
        //WebAssembly.Module
        console.log(resultObject.module);
        //WebAssembly.Instance
        console.log(resultObject.instance);
        //总和
        console.log(resultObject);
        let exports = resultObject.instance.exports;
        memory=exports.memory;
            let arr =[];
            for(let i=0;i<10;i++){
                arr.push(Math.round(Math.random()*10));
            }
            document.querySelector('.sequence-before').innerText=JSON.stringify(arr);
            importArrayToBuffer(memory,arr,exports.getArrayOffset());
            exports.sort();
    });
    </script>
    </body>
    </html>
    

    注意:出现错误
    Uncaught (in promise) TypeError: Failed to execute 'compile' on 'WebAssembly': Incorrect response MIME type. Expected 'application/wasm'.
    因为 从远程服务器加载的Wasm模块文件只有在其HTTP相应结果中被标识为application/wasm类型,才可以被WebAssembly.instantiateStreaming方法正确的编译和处理

    注意
    解决办法:我这里的情况是这样用的springboot的tomcat,所以修改tomcat的mime类型,多添加一个wasm的类型
    https://www.jianshu.com/p/275977cda752

    关系图

    相关文章

      网友评论

          本文标题:通过WasmFiddle平台构建WASM模块

          本文链接:https://www.haomeiwen.com/subject/mdywgctx.html