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&lt;string, vector&lt;string&gt; 这样复杂的 C++ 类型。

总结一下,我有几点建议给你:

    将引用类型更改为指针。

void printmap(const map&lt;string, vector&lt;string&gt; &gt; &amp;ms)

void printmap(const map&lt;string, vector&lt;string&gt; &gt; *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 之间传递字符串

C++ - 通过引用模板函数传递 STL 映射

将 JS 数字数组传递给 emscripten C++ 而无需 reinterpret_cast

Emscripten malloc 和跨 JS 和 C++ 的免费

是否可以使用 emscripten 使用 Javascript 从 C++ 打印字符串?