美文网首页WebAssembly
[wasm] 调用C中的自定义方法

[wasm] 调用C中的自定义方法

作者: 何幻 | 来源:发表于2018-05-16 15:38 被阅读445次

    1. Module.ccall与EMSCRIPTEN_KEEPALIVE

    JavaScript中可以借由wasm调用C中的自定义方法,

    Module.ccall(
        'myFunction',  // C自定义方法的名字
        null,  // 返回值类型
        null,  // 入参类型
        null,  // 入参
    );
    

    默认情况下,Emscripten生成的代码只会调用main()函数,其他函数将被视为无用代码。
    为了避免这件事发生,我们需要在C函数名之前,添加EMSCRIPTEN_KEEPALIVE,它在emscripten.h中声明。

    例子,hello.c

    #include <stdio.h>
    #include <emscripten/emscripten.h>
    
    int main(int argc, char ** argv) {
        printf("Hello World\n");
    }
    
    #ifdef __cplusplus
    extern "C" {
    #endif
    
    int EMSCRIPTEN_KEEPALIVE myFunction(int argc, char ** argv) {
      printf("我的函数已被调用\n");
    }
    
    #ifdef __cplusplus
    }
    #endif
    

    2. 修改编译结果

    编译以上的hello.c文件,

    $ emcc -o hello.html hello.c -s WASM=1 -s "EXTRA_EXPORTED_RUNTIME_METHODS=['ccall']"
    

    注:
    (1)EXTRA_EXPORTED_RUNTIME_METHODS设置了Module的导出函数,
    不导出ccall的话,会报以下错误,

    'ccall' was not exported. add it to EXTRA_EXPORTED_RUNTIME_METHODS (see the FAQ)
    

    (2)为了使用Module.ccall,我们需要修改hello.html文件,
    在文件末尾增加一个<script>标签,

    <script>
      setTimeout(()=>{
        Module.ccall('myFunction', null, null, null);  // 打印:我的函数已被调用
      }, 1000);
    </script>
    

    其中使用setTimeout的原因是,hello.html文件加载hello.js文件的方式是使用了async script

    <script async type="text/javascript" src="hello.js"></script>
    

    参考

    MDN: 编译 C/C++ 为 WebAssembly

    相关文章

      网友评论

        本文标题:[wasm] 调用C中的自定义方法

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