使用 Emscripten 将指向 std::vector 的指针传递给 Javascript,并使用它

Mic*_*mza 2 javascript c++ emscripten

我想在 C++ 中创建一个std::vector(特别是 a std::vector<string>),然后将它(或者更确切地说,指向它的指针)传递给 Javascript,以便能够从直接编写的 Javascript 访问其数据/函数。

到目前为止我可以获得整数指针:

vector<string> myVector;
myVector.push_back("First item");
myVector.push_back("Second item");

EM_ASM_ARGS({
  // Prints out an integer value of the pointer,
  // but I would like to access the object members/data 
  // of myVector
  console.log($0);
}, &myVector);
Run Code Online (Sandbox Code Playgroud)

我在http://kripken.github.io/emscripten-site/docs/api_reference/bind.h.html#register_vector__cCPhttp://kripken.github.io/emscripten-site/docs/porting/connecting_cpp_and_javascript找到了信息/embind.html#built-in-type-conversions关于该register_vector函数

#include <emscripten/bind.h>
EMSCRIPTEN_BINDINGS(Wrappers) {
  register_vector<std::string>("VectorString");
};
Run Code Online (Sandbox Code Playgroud)

它可以用来从 Javascript 世界创建一个新的向量:

var myVector = new Module.VectorString();
Run Code Online (Sandbox Code Playgroud)

但我不知道如何使用它来访问 C++ 世界中已经存在的向量。

Module.Runtime.dynCall('v', $0, []);如果我尝试在指针上使用,如/sf/answers/2052360831/中传递函数指针时,则会出现错误:

Invalid function pointer '380' called with signature 'v'

我尝试了几种不同的签名组合,但它们似乎都失败了(对此我并不感到惊讶:它实际上并不是我正在调用的函数指针,而是指向对象实例的指针)

Mic*_*mza 5

使用/sf/answers/1915525041/reinterpret_cast中的技巧,您可以向从工厂返回的对象添加另一个构造函数,该构造函数除了将整数指针转换为 a 之外什么也不做:register_vectorvector<string>

vector<string> *vectorFromIntPointer(uintptr_t vec) {
  return reinterpret_cast<vector<string> *>(vec);
}

EMSCRIPTEN_BINDINGS(Wrappers) {
  register_vector<string>("VectorString").constructor(&vectorFromIntPointer, allow_raw_pointers());
};
Run Code Online (Sandbox Code Playgroud)

然后,如果您在 C++ 代码中创建向量,则可以通过 JS 代码访问

  • 获取指向它的指针
  • 通过以下方式将指针传递给 JS 代码EM_AMS_ARGS
  • 在 JS 代码中,创建一个新Module.VectorString对象,并将指针值传递给构造函数

如下面的代码所示:

vector<string> myVector;
myVector.push_back("First item");
myVector.push_back("Second item");

EM_ASM_ARGS({
  var myVector = new Module.VectorString($0);
  // Prints "Second item"
  console.log(myVector.get(1));
}, &myVector);
Run Code Online (Sandbox Code Playgroud)