EM_ASM宏
| 宏 |
用途 |
返回值 |
参数访问 |
EM_JS(return_type, function_name, (args), code) |
比ES_ASM更加青大的替代品,用于执行JS代码 |
与return_type匹配 |
使用变量名 |
EM_ASYNC_JS(return_type, function_name, (args), code) |
允许在JS实现中使用 async/await,C函数返回一个Promise |
与return_type匹配 |
使用变量名 |
EM_ASM(code) |
执行嵌入的 JS 代码 |
无 |
无 |
EM_ASM_ARGS(code, args...) |
执行 JS 代码,可传参 |
无 |
使用 $0, $1… |
EM_ASM_INT(code, args...) |
执行 JS 代码,可传参 |
int |
使用 $0, $1… |
EM_ASM_DOUBLE(code, args...) |
执行 JS 代码,可传参 |
double |
使用 $0, $1… |
EM_ASM_INT_V(code) |
执行 JS 代码 |
int |
无 |
EM_ASM_DOUBLE_V(code) |
执行 JS 代码 |
double |
无 |
EMSCRIPTEN_KEEPALIVE |
导出C函数供JS调用 |
无 |
无 |
1、EM_JS
这是 EM_ASM 的一个更推荐的替代品,其用于在 C/C++ 中声明一个用JS编写的函数
1 2 3 4 5 6 7 8 9 10 11 12 13 14
| #include <emscripten.h> #include <iostream>
EM_JS(int, add, (int x, int y), { return x + y; });
int main () { int a = 1; int b = 2; int c = add(a, b); std::cout << "c = " << c << std::endl; return 0; }
|
2、EM_ASYNC_JS
EM_ASYNC_JS 设计的核心目的是让 C/C++ 代码能够调用异步的 JavaScript 代码(如 fetch, setTimeout等)
C/C++函数有返回值(编译使用-s ASYNCIFY)
允许C/C++代码直接等待异步操作完成并获取结果。这需要启用Emscripten的Asyncify功能
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19
| #include <emscripten.h> #include <iostream>
EM_ASYNC_JS(int, add, (int x, int y), { const data = await new Promise((resolve) => { setTimeout(() => { resolve(x + y); }, 2000); }); return data; });
int main () { int a = 1; int b = 2; int c = add(a, b); std::cout << "c = " << c << std::endl; return 0; }
|
3、EM_ASM
最简单的形式,执行嵌入的 JS 代码,详见Emscripten基础
4、EM_ASM_ARGS
通过传参的方式,执行嵌入的JS代码,无返回值
1 2 3 4 5 6 7 8 9 10 11 12 13
| #include <emscripten.h> #include <iostream>
using namespace std;
int main() { int x = 10; int y = 20; EM_ASM_ARGS({ alert(`current data ${$0} ${$1}`); }, x, y); cout << x * y << endl; }
|
5、EM_ASM_INT
通过传参的方式,执行JS代码并返回一个int类型的值,详见Emscripten基础
6、EM_ASM_DOUBLE
通过传参的方式,执行JS代码并返回一个double类型的值,详见Emscripten基础
7、EM_ASM_INT_V
通过无参的方式,执行JS代码并返回一个int类型的值
1 2 3 4 5 6 7 8 9 10 11 12 13
| #include <emscripten.h> #include <iostream>
using namespace std;
int main() { int x = EM_ASM_INT_V({ let a = 1; let b = 2; return a + b; }); cout << x << endl; }
|
8、EM_ASM_DOUBLE_V
通过无参的方式,执行JS代码并返回一个double类型的值
1 2 3 4 5 6 7 8 9 10 11 12 13
| #include <emscripten.h> #include <iostream>
using namespace std;
int main() { double x = EM_ASM_DOUBLE_V({ let a = 1.1; let b = 2.2; return a + b; }); cout << x << endl; }
|
9、EMSCRIPTEN_KEEPALIVE
Emscripten的EMSCRIPTEN_KEEPALIVE宏用于确保C/C++函数在编译后不会被编译器优化掉,并且可以从JavaScript中调用
这对于在Web环境中使用C/C++代码非常重要
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20
| #include <emscripten.h> #include <iostream>
extern "C" { EMSCRIPTEN_KEEPALIVE int add(int a, int b) { return a + b; }
EMSCRIPTEN_KEEPALIVE const char* get_string() { return "Hello from C++!"; }
EMSCRIPTEN_KEEPALIVE void print_message() { std::cout << "Message printed from C++" << std::endl; } }
|
通过编译命令将这些方法导出到test.js中以供JS调用
1
| emcc hello-world.cpp -s WASM=1 -s EXPORTED_FUNCTIONS='["_add", "_get_string", "_print_message"]' -o test.js
|
在HTML中调用方法
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44
| <!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <meta name="viewport" content="width=device-width, initial-scale=1.0"> <title>WebAssembly Demo</title> <style> .button-container { margin: 20px; text-align: center; } button { padding: 10px 20px; margin: 0 10px; font-size: 16px; cursor: pointer; } </style> </head> <body> <div class="button-container"> <button class="button" onclick="callAdd()">调用 add(5, 7)</button> <button class="button" onclick="callGetString()">调用 get_string()</button> <button class="button" onclick="callPrintMessage()">调用 print_message()</button> </div> <script src="./test.js"></script> <script> Module.onRuntimeInitialized = function() { console.log('WebAssembly模块已加载');
window.callAdd = function() { const result = Module._add(5, 7); alert(`5 + 7 = ${result}`); };
window.callGetString = function() { const cStr = Module._get_string(); alert(`C++返回字符串: ${cStr}`); };
window.callPrintMessage = function() { Module._print_message(); alert('已调用print_message,请查看控制台输出'); }; }; </script> </body> </html>
|