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>