01 EM_ASM 宏应用
emcc wasm060301.c -o wasm060301.html
#include <stdio.h>
#include <emscripten.h>
// EM_ASM_ 宏可带简单参数,但是返回的number值被截断了
void test01() {
float sum = EM_ASM_({
var sum = $0 + $1;
console.log("console.log(sum):" + sum);
return sum;
}, 1.1, 2.2);
printf("printf(sum(1.1, 2.2)): %f\n", sum);
}
// EM_ASM_* 宏可带简单参数,指定double类型后,不会被截断
void test02() {
float sum = EM_ASM_DOUBLE({
var sum = $0 + $1;
console.log("console.log(sum):" + sum);
return sum;
}, 1.1, 2.2);
printf("EM_ASM_DOUBLE printf(sum(1.1, 2.2)): %f\n", sum);
}
void test03() {
int v = EM_ASM_INT({return 42;}, 0);
printf("EM_ASM_INT printf %d\n", v);
}
void test04() {
EM_ASM_({
console.log("$0: ", $0);
console.log("$1: ", $1);
}, 1, 2);
}
void test05() {
EM_ASM_({
for(var i = 0; i < arguments.length; i++) {
console.log("$", i, ":", arguments[i]);
}
}, 1, 2, 3);
}
void test06() {
EM_ASM_({
//var args = ([$0, $1]);
var args = arguments;
console.log("args: ", args);
}, 1, 2);
}
// emcc wasm060301.c -o wasm060301.html
int main() {
EM_ASM(console.log("你好,Emscripten!"));
EM_ASM(console.log("hello world!"); console.log("hello world!"));
EM_ASM(
console.log("hello world!..");
console.log("hello world!..");
);
EM_ASM(
//console.log("hello world!...") // 没有分号运行时错误
console.log("hello world!...")
);
test01();
test02();
test03();
int v2 = EM_ASM_INT_V({return 42});
printf("EM_ASM_INT_V printf %d\n", v2);
int v3 = EM_ASM_INT_V(return 42);
printf("EM_ASM_INT_V printf %d\n", v3);
test04();
test05();
test06();
return 0;
}
02 C++调用js
emcc -std=c++11 --js-library wasm060402_package.js -s"EXPORTED_RUNTIME_METHODS=['ptrToString', 'maybeCStringToJsString']" wasm060402.cc -o wasm060402.html
wasm060402_package.js
// package.js
// emcc -std=c++11 --js-library wasm060402_package.js -s EXPORTED_RUNTIME_METHODS="['ccall', 'getValue', 'cwrap', 'maybeCStringToJsString', 'ptrToString']" -s EXPORTED_FUNCTIONS="['_malloc', '_free', '_main']" wasm060402.cc -o wasm060402.html
mergeInto(LibraryManager.library, {
my_run_script1: function(code, $arg) {
eval(code);
console.log(code);
console.log(maybeCStringToJsString(code));
},
my_run_script2: function(code) {
//eval(Pointer_stringify(code));
//eval(UTF8ToString(code));
eval(maybeCStringToJsString(code));
console.log(maybeCStringToJsString(code));
//console.log(UTF8ToString(code));
},
my_run_script3: function(code, $arg) {
//eval(Pointer_stringify(code));
//eval(UTF8ToString(code));
eval(maybeCStringToJsString(code));
console.log(maybeCStringToJsString(code));
//console.log(UTF8ToString(code));
},
// 这个没搞明白
my_run_script_string: function(code) {
console.log(code);
//var s = eval(ptrToString(code));
//var s = eval(Pointer_stringify(code));
var s = eval(UTF8ToString(code));
var p = _my_run_script_string;
console.log(p);
if (!p.bufferSize || p.bufferSize < s.length()+1) {
if (p.bufferSize) _free(p.buffer);
p.bufferSize = lengthBytesUTF8(s)+1;
p.buffer = _malloc(p.bufferSize);
}
stringToUTF8(s, p.buffer, 1024*8);
return p.buffer;
}
});
wasm060402.cc
// emcc -std=c++11 --js-library wasm060402_package.js -s"EXPORTED_RUNTIME_METHODS=['ptrToString', 'maybeCStringToJsString']" wasm060402.cc -o wasm060402.html
// emcc -std=c++11 --js-library wasm060402_package.js -s"EXPORTED_RUNTIME_METHODS=['ptrToString', 'maybeCStringToJsString']" wasm060402.cc -o wasm060402.html
// https://www.cntofu.com/book/150/zh/ch2-c-js/ch2-04-data-exchange.md
// emcc -s WASM=1 -o wasm060402.html --js-library wasm060402_package.js -s "EXPORTED_RUNTIME_METHODS=['ccall', 'cwrap', 'ptrToString']" -s ASSERTIONS=1 -O1 -O2 -O3 -std=c++11 -s ALLOW_MEMORY_GROWTH=1 -s NO_EXIT_RUNTIME=1 wasm060402.cc
#include <emscripten.h>
extern "C" void EMSCRIPTEN_KEEPALIVE my_run_script1(const char* s, ...);
extern "C" void EMSCRIPTEN_KEEPALIVE my_run_script2(const char* s, ...);
extern "C" void EMSCRIPTEN_KEEPALIVE my_run_script3(const char* s, ...);
void test_error() {
my_run_script1("console.log($arg)", 42); // error
//1053
//console.log($arg)
my_run_script1("console.log(arguments[1])", 42); // error
//1071
//console.log(arguments[1])
my_run_script2("console.log(arguments)", 42); // error
// console.log(arguments)
my_run_script2("console.log(arguments)", 1, 2, 3); // error
// console.log(arguments)
}
void test01() {
auto jsCode = R"(
console.log('arg1:', getValue(arguments[1] + 0, 'i32'));
console.log('arg2:', getValue(arguments[1] + 4, 'i32'));
console.log('arg3:', getValue(arguments[1] + 8, 'double'));
console.log('arg4:', maybeCStringToJsString(getValue(arguments[1] + 16, 'i64')));
console.log('arg4:', UTF8ToString(getValue(arguments[1] + 16, 'i64')));
)";
my_run_script3(jsCode, 43, 2017, 3.14, "hello");
// 输出结果
//arg1: 43
//arg2: 2017
//arg3: 3.14
//arg4: hello
//arg4: hello
//console.log('arg1:', getValue(arguments[1] + 0, 'i32'));
//console.log('arg2:', getValue(arguments[1] + 4, 'i32'));
//console.log('arg3:', getValue(arguments[1] + 8, 'double'));
//console.log('arg4:', maybeCStringToJsString(getValue(arguments[1] + 16, 'i64')));
//console.log('arg4:', UTF8ToString(getValue(arguments[1] + 16, 'i64')));
}
void test02() {
auto jsCode = R"(
console.log('arg1:', HEAP32[(arguments[1] + 0) / 4]);
console.log('arg2:', HEAP32[(arguments[1] + 4) / 4]);
console.log('arg3:', HEAP32[(arguments[1] + 8) / 4]);
console.log('arg4:', maybeCStringToJsString(HEAP32[(arguments[1] + 12) / 4]));
)";
my_run_script2(jsCode, 1, 2, 3, "hello");
//arg1: 1
//arg2: 2
//arg3: 3
//arg4: hello
//
//console.log('arg1:', HEAP32[(arguments[1] + 0) / 4]);
//console.log('arg2:', HEAP32[(arguments[1] + 4) / 4]);
//console.log('arg3:', HEAP32[(arguments[1] + 8) / 4]);
//console.log('arg4:', maybeCStringToJsString(HEAP32[(arguments[1] + 12) / 4]));
}
void test03() {
auto jsCode = R"(
for(let i = 0; i < arguments.length; i++) {
console.log("arg" + i.toString() + ":" + maybeCStringToJsString(HEAP32[(arguments[1] + 4*i) >> 2]));
}
)";
my_run_script2(jsCode, "hello", "world", 2, 3);
//arg0:hello
//arg1:world
//for(let i = 0; i < arguments.length; i++) {
// console.log("arg" + i.toString() + ":" + maybeCStringToJsString(HEAP32[(arguments[1] + 4*i) >> 2]));
//}
}
void test04() {
auto jsCode = R"(
console.log('arg1:', getValue(arguments[1] + 8*0, 'double'));
console.log('arg2:', getValue(arguments[1] + 8*1, 'double'));
console.log('arg3:', getValue(arguments[1] + 8*2, 'double'));
)";
my_run_script2(jsCode, 1.1f, 2.2f, 3.3f);
//arg1: 1.100000023841858
//arg2: 2.200000047683716
//arg3: 3.299999952316284
//console.log('arg1:', getValue(arguments[1] + 8*0, 'double'));
//console.log('arg2:', getValue(arguments[1] + 8*1, 'double'));
//console.log('arg3:', getValue(arguments[1] + 8*2, 'double'));
}
void test05() {
auto jsCode = R"(
console.log('arg1:', maybeCStringToJsString(getValue(arguments[1] + 0, 'i32')));
console.log('arg2:', getValue(arguments[1] + 4, 'i32'));
console.log('arg3:', getValue(arguments[1] + 8, 'double'));
console.log('arg4:', getValue(arguments[1] + 16, 'i32'));
)";
my_run_script2(jsCode, "hello", 43, 3.14f, 2022);
//arg1: hello
//arg2: 43
//arg3: 3.140000104904175
//arg4: 2022
//console.log('arg1:', maybeCStringToJsString(getValue(arguments[1] + 0, 'i32')));
//console.log('arg2:', getValue(arguments[1] + 4, 'i32'));
//console.log('arg3:', getValue(arguments[1] + 8, 'double'));
//console.log('arg4:', getValue(arguments[1] + 16, 'i32'));
}
#include <string>
#include <stdlib.h>
extern "C" const char* my_run_script_string(const char* s, ...);
void test06() {
printf("###############\n");
std::string s0 = my_run_script_string("console.log('hello')");
std::string s1 = my_run_script_string("console.log('world')");
printf("%s, %s\n", s0.c_str(), s1.c_str());
}
int main() {
test_error();
test01();
test02();
test03();
test04();
test05();
//test06(); // 这个没搞明白
return 0;
}
03 js 调用 c++
emcc -std=c++11 -s EXPORTED_FUNCTIONS="['_test01', '_mymain', '_main']" wasm060501.cc -o wasm060501.html
// wasm060501.cc
//#include "wasm060501.h"
#include <stdio.h>
#include <emscripten.h>
#if defined(__cplusplus)
#define CAPI_EXPORT(rettype) extern "C" rettype
#else
#define CAPI_EXPORT(rettype) rettype
#endif
// emcc -std=c++11 -s EXPORTED_RUNTIME_METHODS="['ccall', 'getValue', 'cwrap', 'maybeCStringToJsString', 'ptrToString']" -s EXPORTED_FUNCTIONS="['_mymain']" wasm060501.cc -o wasm060501.html
// emcc -std=c++11 -s EXPORTED_FUNCTIONS="['_test01', '_mymain', '_main']" wasm060501.cc -o wasm060501.html
CAPI_EXPORT(int) mymain() {
printf("hello, mymain\n");
return 0;
}
extern "C" int test01() {
printf("test01\n");
return 43;
}
int preMain = emscripten_run_script_int(R"==(
// 禁止main()函数的自动运行
Module.noInitialRun = true;
showdRunNow = false;
console.log("== js call myamin ==");
// 调用mymain()函数
let ret = Module._mymain();
console.log("myamin()=" + ret);
console.log("\n js call test01 \n");
ret = Module._test01();
console.log("test01()=" + ret);
)==");
void test02() {
printf("test02\n");
}
int test03() {
printf("test03\n");
return 3;
}
int main() {
printf("\nhello world\n");
test02();
test03();
mymain();
//Module._test01();
return 0;
}
04 消息机制
emcc -std=c++11 wasm060603.cc -o wasm060603.html
wasm060603.cc
#include <stdio.h>
#include <SDL.h>
#include <emscripten.h>
// emcc -std=c++11 wasm060603.cc -o wasm060603.html
SDL_Surface* screen = NULL;
void do_web_frame() {
SDL_Event event;
while(SDL_PollEvent(&event)) {
switch(event.type) {
case SDL_QUIT:
break;
case SDL_MOUSEMOTION:
printf("mouse(x, y): (%d, %d)\n", event.button.x, event.button.y);
fflush(stdout);
break;
}
}
}
int main() {
SDL_Init(SDL_INIT_VIDEO);
screen = SDL_SetVideoMode(1024, 768, 32, SDL_ANYFORMAT);
// 在 do_web_frame 中通过SDL_PollEvent获取输入消息
emscripten_set_main_loop(do_web_frame, 0, 0);
return 0;
}