首页
学习
活动
专区
圈层
工具
发布
首页
学习
活动
专区
圈层
工具
MCP广场
社区首页 >问答首页 >使用emscripten将JS对象传递给C++的内置方式

使用emscripten将JS对象传递给C++的内置方式
EN

Stack Overflow用户
提问于 2022-07-25 18:10:44
回答 1查看 186关注 0票数 2

是否有一种简单的内置方式将JS对象传递给C++?

我试着用显而易见的方法:

echo.cpp:

代码语言:javascript
运行
复制
#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:

代码语言:javascript
运行
复制
import initEM from "./echo.mjs";

var mod = await initEM();

export function echo(x){
  mod.ccall("echo", "void", ["object"], [x]);
}

echo({attr: 9});

汇编使用:

代码语言:javascript
运行
复制
emcc ./echo.cpp -o ./echo.mjs \
  -sEXPORTED_FUNCTIONS=_main,_echo \
  -sEXPORTED_RUNTIME_METHODS=ccall,cwrap,registeredTypes \
  -lembind --bind

但我有个错误:

代码语言:javascript
运行
复制
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:

代码语言:javascript
运行
复制
#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:

代码语言:javascript
运行
复制
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});

(编译时使用与另一件相同的内容)

问题:

  1. 为什么这还没有出现在ccall/cwrap函数中呢?
  2. 为什么emscripten不将val.toWireType公开为模块对象的属性(例如,为什么我必须循环遍历所有类型才能找到它),或者我遗漏了什么?
EN

回答 1

Stack Overflow用户

回答已采纳

发布于 2022-07-25 19:02:10

通过文档

代码语言:javascript
运行
复制
EMSCRIPTEN_BINDINGS(my_module) {
  function("lerp", &lerp);
}

my_module只是一个(全局的)唯一的名称,您必须添加,它没有任何其他用途。

代码语言:javascript
运行
复制
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);
}

现在,您可以不使用echo从JS调用ccall

代码语言:javascript
运行
复制
Module.echo({addr: 9});

请注意,这在webworker中不能很好地工作;echo方法在Module中的注册是作为WASM初始化的一部分完成的,并且只在初始化线程中完成。

虽然EMSCRITEN_BINDINGS看起来很神奇,但它基本上只是做了一个静态的全局函数,并在静态构建时调用它。它是

代码语言:javascript
运行
复制
function("echo", echo);

这完成了所有工作;它确定了echo的参数,并构建了一个JS包装器,该包装器使用名称"echo"转换参数并调用C++函数echo

票数 2
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/73113594

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档