Emscripten 传递 stl c++ map 参数
Posted
技术标签:
【中文标题】Emscripten 传递 stl c++ map 参数【英文标题】:Emscripten pass stl c++ map parameter 【发布时间】:2019-04-29 14:09:31 【问题描述】:我不知道如何为以下函数调用 JS 生成的代码:
void printmap(const map<string, vector<string> > &ms)
map<string, vector<string> >::const_iterator m1i;
for (m1i = ms.begin(); m1i != ms.end(); m1i++)
printf("%s:\n", m1i->first.c_str());
vector<string>::const_iterator m2i;
for (m2i = m1i->second.begin(); m2i != m1i->second.end(); m2i++)
printf("\t%s\n", m2i->c_str());
更具体地说,准备'ms'参数的JS是什么样的?
【问题讨论】:
【参考方案1】:使用Embind map and vector 非常可行
来自网站的示例: C++ 代码
#include <emscripten/bind.h>
#include <string>
#include <vector>
using namespace emscripten;
std::vector<int> returnVectorData ()
std::vector<int> v(10, 1);
return v;
std::map<int, std::string> returnMapData ()
std::map<int, std::string> m;
m.insert(std::pair<int, std::string>(10, "This is a string."));
return m;
EMSCRIPTEN_BINDINGS(module)
function("returnVectorData", &returnVectorData);
function("returnMapData", &returnMapData);
// register bindings for std::vector<int> and std::map<int, std::string>.
register_vector<int>("vector<int>");
register_map<int, std::string>("map<int, string>");
Js 代码
var retVector = Module['returnVectorData']();
// vector size
var vectorSize = retVector.size();
// reset vector value
retVector.set(vectorSize - 1, 11);
// push value into vector
retVector.push_back(12);
// retrieve value from the vector
for (var i = 0; i < retVector.size(); i++)
console.log("Vector Value: ", retVector.get(i));
// expand vector size
retVector.resize(20, 1);
var retMap = Module['returnMapData']();
// map size
var mapSize = retMap.size();
// retrieve value from map
console.log("Map Value: ", retMap.get(10));
// figure out which map keys are available
// NB! You must call `register_vector<key_type>`
// to make vectors available
var mapKeys = retMap.keys();
for (var i = 0; i < mapKeys.size(); i++)
var key = mapKeys.get(i);
console.log("Map key/value: ", key, retMap.get(key));
// reset the value at the given index position
retMap.set(10, "OtherValue");
以上面的sn-p作为参考,应该不难达到你的要求。
【讨论】:
【参考方案2】:您可以不在 JS 中调用您的 printmap()
。
WebAssembly 当前defines number types only:32/64 位整数/浮点数。由于这个限制,Emscripten 编译的 WASM 代码可以通过以下类型与 JS 交互:
-
数字类型(整数和浮点数)
指针类型(通过将整数视为 WASM 内存地址 0x00000000 的偏移量)
字节(或整数)数组的指针
一个字符串的指针(虽然它是isn't simple)
类实例的指针(通过Embind)
我不知道指针和引用的行为如何不同,thus you cannot use a reference type to interact with JS。
正如您在这里猜到的那样,没有办法操作像 map<string, vector<string>
这样复杂的 C++ 类型。
总结一下,我有几点建议给你:
-
将引用类型更改为指针。
void printmap(const map<string, vector<string> > &ms)
到
void printmap(const map<string, vector<string> > *ms)
-
为
ms
写一个init函数,这样你就可以在JS中做这样的事情:
let map_ptr = module._initmap();
...Do something..
module._printmap(map_ptr);
-
避免在JS端直接使用这种复杂的C/C++类型,或者为
ms
制作getter和setter函数。
【讨论】:
以上是关于Emscripten 传递 stl c++ map 参数的主要内容,如果未能解决你的问题,请参考以下文章
使用 emscripten 将字符串从 C++ 传递给 JS
如何通过 emscripten 在 C++ 和 javascript 之间传递字符串
将 JS 数字数组传递给 emscripten C++ 而无需 reinterpret_cast