2

I would like to create a std::vector (specifically, a std::vector<string>) in C++, and then pass it (or rather, a pointer to it) to Javascript, in order to be able to access its data/functions from directly-written Javascript.

So far I can get the integer pointer:

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

I have found information at 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 about the register_vector function

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

which can be used to create a new vector from the Javascript world:

var myVector = new Module.VectorString();

but I can't figure out how to use this to access vector that already exists in the C++ world.

If I try to use Module.Runtime.dynCall('v', $0, []); on the pointer, as in https://stackoverflow.com/a/29319440/1319998 when passing function pointers, then I get an error:

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

I have tried a few different combinations of signatures, and they all seem to fail (Which I'm not really surprised about: it's not really a function pointer I'm calling, but a pointer to an instance of an object)

2
  • I've edited this question to explain why it's not a duplicate of stackoverflow.com/a/29319440/1319998 . The solution there doesn't apply in this case: that was calling a C++ function pointer from Javascript, while this question is about is accessing members of an existing C++ object. Commented Mar 29, 2015 at 10:26
  • I've also edited the title of the one at stackoverflow.com/a/29319440/1319998 (it's my question) to hopefully better show why it's different. Commented Mar 29, 2015 at 10:33

1 Answer 1

5

Using the reinterpret_cast trick from https://stackoverflow.com/a/27364643/1319998 you can add another constructor to the object returned from the register_vector factory that does nothing but converts an integer pointer to a 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());
};

Then if you create a vector in C++ code, you can access in JS code by

  • Getting a pointer to it
  • Passing the pointer to JS code via EM_AMS_ARGS
  • In the JS Code, create a new Module.VectorString object passing in the pointer value to the constructor

As in the following code:

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);
Sign up to request clarification or add additional context in comments.

2 Comments

Where is the documentation for .get function,How did you find this get function for myVector? Please post a link thnx.
Five years later... the get method is added by register_vector, see emscripten/bind.h

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.