[英]Built-in way to pass JS objects to C++ using emscripten
echo.cpp:回声.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
script.mjs:脚本.mjs:
import initEM from "./echo.mjs";
var mod = await initEM();
export function echo(x){
mod.ccall("echo", "void", ["object"], [x]);
}
echo({attr: 9});
Compiled using:编译使用:
emcc ./echo.cpp -o ./echo.mjs \
-sEXPORTED_FUNCTIONS=_main,_echo \
-sEXPORTED_RUNTIME_METHODS=ccall,cwrap,registeredTypes \
-lembind --bind
But I got an error:但我得到一个错误:
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
echo.cpp:回声.cpp:
#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
script.mjs:脚本.mjs:
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});
(Compiled using same thing as the other one) (使用与另一个相同的东西编译)
ccall
/ cwrap
functions?为什么这不在ccall
/ cwrap
函数中?val.toWireType
as an attribute of the module object (ie why do I have to loop through all types to find it), or is there something I've missed?为什么 emscripten 不将val.toWireType
作为模块 object 的属性公开(即为什么我必须遍历所有类型才能找到它),或者我错过了什么?EMSCRIPTEN_BINDINGS(my_module) {
function("lerp", &lerp);
}
my_module
is just a (globally) unique name you have to add, it doesn't have any other purpose. 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);
}
now you can invoke echo
from JS without using ccall
:现在您可以在不使用ccall
的情况下从 JS 调用echo
:
Module.echo({addr: 9});
note that this doesn't work well from a webworker;请注意,这对网络工作者来说效果不佳; the registration of the echo
method in Module
is done as part of WASM initialization, and only in the initializing thread.在Module
中注册echo
方法是作为 WASM 初始化的一部分完成的,并且仅在初始化线程中完成。
While EMSCRITEN_BINDINGS
looks magical, it basically just makes a static global function and calls it at static construction time.虽然EMSCRITEN_BINDINGS
看起来很神奇,但它基本上只是使 static 全局 function 并在 static 构建时间调用它。 It is这是
function("echo", echo);
that does all of the work;完成所有工作; it determines the arguments of echo
, and builds a JS wrapper that converts arguments and calls the C++
function echo
, using the name "echo"
. it determines the arguments of echo
, and builds a JS wrapper that converts arguments and calls the C++
function echo
, using the name "echo"
.
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.