2

I cannot figure out how to call the JS generated code for the following function:

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());
    }
}

more specifically, what does the JS look like to prepare the 'ms' parameter ?

Waslap
  • 572
  • 3
  • 23

2 Answers2

1

It is pretty much feasible by using the Embind map and vector

example from site: C++ Code

    #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 Code

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");

Take the above snippet as a reference, it should not be hard to achieve your requirement.

Anil8753
  • 2,663
  • 4
  • 29
  • 40
0

You can not call your printmap() in JS.

WebAssembly currently defines number types only: 32/64bit integer/float. Because of this limitation, Emscripten compiled WASM code can interact with JS via the following types:

  1. Number types (integers and floats)
  2. Pointer types (by treating an integer an offset to the WASM memory address 0x00000000)
    • A pointer of a byte (or integer) array
    • A pointer of a string (though it isn't simple)
    • A pointer of a class instance (via Embind)

I don't know how but pointers and references behave differently, thus you cannot use a reference type to interact with JS.

As you can guess here, there is no way to manipulate such complex C++ types like map<string, vector<string>.

I sum up, I have a few suggestions for you:

  1. Change the reference type to a pointer.

void printmap(const map<string, vector<string> > &ms)

to

void printmap(const map<string, vector<string> > *ms)

  1. Write a init function for ms so that you can do something like this in JS:
let map_ptr = module._initmap();
...Do something..
module._printmap(map_ptr);
  1. Just avoid using such complex C/C++ types in JS side directly, or make getter & setter functions for ms.
Bumsik Kim
  • 5,853
  • 3
  • 23
  • 39