回声.cpp:
#include <iostream> #include <emscripten.h> #include <emscripten/val.h> using emscripten::val; #ifdef __cplusplus extern "C" { #endif EMSCRIPTEN_KEEPALIVE void echo(val x){ val::global("console").call<void>("log", x); } int main(int argc, char **argv){ return 0; } #ifdef __cplusplus } #endif
脚本.mjs:
import initEM from "./echo.mjs"; var mod = await initEM(); export function echo(x){ mod.ccall("echo", "void", ["object"], [x]); } echo({attr: 9});
编译使用:
emcc ./echo.cpp -o ./echo.mjs \ -sEXPORTED_FUNCTIONS=_main,_echo \ -sEXPORTED_RUNTIME_METHODS=ccall,cwrap,registeredTypes \ -lembind --bind
但我得到一个错误:
Uncaught TypeError: Cannot read properties of undefined (reading 'refcount') at __emval_incref (echo.mjs:2622:29) at echo.wasm:0x1957 at echo.wasm:0x1842 at echo.wasm:0x121c at echo.wasm:0x110f at echo.wasm:0x104a at echo.mjs:1639:22 at Object.ccall (echo.mjs:845:18) at echo (script.mjs:6:7) at script.mjs:9:1
#include <iostream> #include <emscripten.h> #include <emscripten/val.h> using emscripten::val; using emscripten::internal::EM_VAL; #ifdef __cplusplus extern "C" { #endif EMSCRIPTEN_KEEPALIVE void echo(EM_VAL x_ptr){ // converts it to object from the pointer val x = val::take_ownership(x_ptr); val::global("console").call<void>("log", x); } int main(int argc, char **argv){ return 0; } #ifdef __cplusplus } #endif
import initEM from "./echo.mjs"; var mod = await initEM(); let objToC = null; for(let tp of Object.values(mod.registeredTypes)){ if(tp.name=="emscripten::val"){ // turns it into a pointer (I think) objToC = (v) => tp.toWireType(null, v); break; } } if(objToC==null){ throw new ReferenceError("val.toWireType not found"); } export function echo(x){ mod.ccall("echo", "void", ["number"], [objToC(x)]); } echo({attr: 9});
(使用与另一个相同的东西编译)
ccall
cwrap
val.toWireType
通过文档:
EMSCRIPTEN_BINDINGS(my_module) { function("lerp", &lerp); }
my_module只是您必须添加的(全局)唯一名称,它没有任何其他用途。
my_module
void echo(EM_VAL x_ptr){ // converts it to object from the pointer val x = val::take_ownership(x_ptr); val::global("console").call<void>("log", x); } EMSCRIPTEN_BINDINGS(my_bindings) { function("echo", echo); }
现在你可以从 JS 调用echo而不使用ccall:
echo
Module.echo({addr: 9});
请注意,这对网络工作者来说效果不佳;echo方法的注册Module是作为 WASM 初始化的一部分完成的,并且仅在初始化线程中完成。
Module
虽然EMSCRITEN_BINDINGS看起来很神奇,但它基本上只是制作了一个静态全局函数并在静态构造时调用它。这是
EMSCRITEN_BINDINGS
function("echo", echo);
完成所有工作;它确定 的参数echo,并构建一个 JS 包装器,用于转换参数并使用名称调用C++函数。echo``"echo"
C++
echo``"echo"