一、main()函数与生命周期
对于Emscripten来说,main()函数既不是必需的,也不控制运行时生命周期。
1、test.c
#include <stdio.h>
#include <emscripten.h>
//extern "C" {
EMSCRIPTEN_KEEPALIVE
int show_answer()
{
return 42;
}
int main()
{
printf("hello world\n");
return 1;
}
//}
2、test.html
<!doctype html>
<html>
<head>
<meta charset="UTF-8">
<title>Web--Test</title>
<style>
</style>
</head>
<body>
<div class="button_box">
<div class="items">
<button type="button" onClick="start()">start</button>
<button type="button" onClick="stop()">stop</button>
</div>
</div>
<script async type="text/javascript" src="test.js"></script>
<script>
function start(){
//Module._malloc100M();
let ans = Module._show_answer();
console.log("ans:"+ans);
}
</script>
</body>
</html>
二、消息循环
1、C++中的消息循环
int main()
{
while(1){
msg_loop();
}
return 0;
}
网页中的JavaScript脚本是单线程运行的。如果一个带有消息循环的C/C++程序不加处理,直接使用Emscripten编译后导入网页中运行,则消息循环不退出,并堵塞页面程序的运行,导致DOM无法更新,使整个页面失去响应。
为此,Emscripten提供了一组函数用于消息循环的模拟及调度执行。
2、emscripten_set_main_loop()
该函数用于创建主消息循环,在消息循环建立后按照设定的频率调用指定的回调函数。
void emscripten_set_main_loop(em_callback_func func,int fps,int simulate_infinite_loop)
func:消息处理回调函数。
fps:消息循环的执行帧率。如果该参数小于等于0,则使用页面的requestAnimationFrame机制调用消息处理函数。该机制可以确保页面刷新率与显示器刷新率对等。(对于需要执行图形渲染任务的程序,使用该机制可以得到平滑的渲染速度)。
simulate_infinite_loop:是否模拟“无限循环”。当设为1时,emscripten_set_main_loop()函数的后续代码不执行,main()函数栈未销毁。无论是0还是1,消息处理函数都会按照设定的帧率无限执行。
3、test.c
#include <stdio.h>
#include <emscripten.h>
//extern "C" {
EMSCRIPTEN_KEEPALIVE
void msg_loop()
{
static int count= 0;
if(count%60 ==0)
{
printf("count:%d\n",count);
}
count++;
}
EMSCRIPTEN_KEEPALIVE
void pause_main_loop()
{
emscripten_pause_main_loop();
printf("pause main loop\n");
}
EMSCRIPTEN_KEEPALIVE
void resume_main_loop()
{
emscripten_resume_main_loop();
printf("resume main loop\n");
}
EMSCRIPTEN_KEEPALIVE
void cancel_main_loop()
{
emscripten_cancel_main_loop();
printf("cancel main loop\n");
}
int main()
{
printf("main loop start\n");
emscripten_set_main_loop(msg_loop,0,1);
printf("main loop end\n");
return 1;
}
//}
4、test.html
<!doctype html>
<html>
<head>
<meta charset="UTF-8">
<title>Web--Test</title>
<style>
</style>
</head>
<body>
<div class="button_box">
<div class="items">
<button id=pause onClick=pause()>pause</button>
<button id=resume onClick=resume()>resume</button>
<button id=cancel onClick=cancel()>cancel</button>
</div>
</div>
<script async type="text/javascript" src="test.js"></script>
<script>
function pause(){
Module._pause_main_loop();
}
function resume(){
Module._resume_main_loop();
}
function cancel(){
Module._cancel_main_loop();
}
Module={};
Module.onRuntimeInitiallized =function(){
document.getElementById("pause").disabled=false;
document.getElementById("resume").disabled=false;
document.getElementById("cancel").disabled=false;
}
</script>
</body>
</html>
Emscripten提供的消息循环函数对C/C++代码来说是侵入式的,因此在工程中应尽可能避免使用。