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

Pass pointer to std::vector to Javascript using Emscripten, and use it

我想在 C++ 中创建一个 std::vector(具体来说,一个 std::vector<string>),然后将它(或者更确切地说,一个指向它的指针)传递给 Javascript,在为了能够从直接编写的 Javascript.

访问它的 data/functions

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

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([=12=]);
}, &myVector);

我在 http://kripken.github.io/emscripten-site/docs/api_reference/bind.h.html#register_vector__cCP and http://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");
};

可用于从 Javascript 世界创建新矢量:

var myVector = new Module.VectorString();

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

如果我尝试在指针上使用 Module.Runtime.dynCall('v', [=18=], []);,如在传递函数指针时在 中那样,则会出现错误:

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

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

使用 中的 reinterpret_cast 技巧,您可以向从 register_vector 工厂返回的对象添加另一个构造函数,它除了将整数指针转换为 vector<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());
};

那么如果你在C++代码中创建一个vector,你可以通过

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

如以下代码:

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

EM_ASM_ARGS({
  var myVector = new Module.VectorString([=11=]);
  // Prints "Second item"
  console.log(myVector.get(1));
}, &myVector);