WebAssembly

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

2018-05-16  本文已影响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

上一篇下一篇

猜你喜欢

热点阅读