return pointer from JavaScript to C++

223 views
Skip to first unread message

Josh A

unread,
Dec 9, 2015, 9:13:51 AM12/9/15
to emscripten-discuss
Hi all,

This seems like it should be really straight forward, but I can't find an example of this.

I am trying to expose some scripting on my software:

With embind I expose an Interface that should be implemented by javascript.  This works fine.

Now I want to call some code that takes a provided js implementation of the interface, instatiates it and returns a pointer to C++ of the created object.  I can do the js call fine and everything works, but I can't seem to find how to get the pointer from the js back to the C++, either using an emscripten_run_script variant or using embind vars or some other method.

I have tried searching, reading through docs and looking at the test code, but still can't find an example of this.  Can someone please point me to the right place?

Thanks++
Josh

Brion Vibber

unread,
Dec 9, 2015, 12:54:44 PM12/9/15
to emscripten Mailing List

Simply return the pointer from the function with the 'return' statement, like any other function return value. Remember that pointers are just integers.

-- brion

--
You received this message because you are subscribed to the Google Groups "emscripten-discuss" group.
To unsubscribe from this group and stop receiving emails from it, send an email to emscripten-disc...@googlegroups.com.
For more options, visit https://groups.google.com/d/optout.

Joshua Auerbach

unread,
Dec 9, 2015, 3:56:58 PM12/9/15
to emscripte...@googlegroups.com
Are you sure it's so simple?

Calling this from C++ does not work properly:

TestStruct* testPtr = reinterpret_cast<TestStruct*>( emscripten_run_script_int("new Module.TestStruct(2.2);") );

while I can create TestStructs with the same constructor fine from within JavaScript (and emscripten_run_script_int works if I am actually returning an int)

note:

struct TestStruct {
    double a;
    TestStruct(double x) : a(x) {}
};

EMSCRIPTEN_BINDINGS(my_module) {
emscripten::class_<TestStruct>("TestStruct")
        .constructor<float>()
        .property("a", &TestStruct::a);
}


Thanks,
Josh
-- 
Dr. Joshua E. Auerbach
Postdoctoral Researcher
Laboratory of Intelligent Systems
École Polytechnique Fédérale de Lausanne

Brion Vibber

unread,
Dec 9, 2015, 4:30:52 PM12/9/15
to emscripten Mailing List
Ah, I see -- the JS object that's created isn't actually a pointer in this case, it's a wrapper object (that contains a pointer). Digging into the wrapper object to find the pointer is probably gauche...

Easiest way may be to define a virtual factory class in C++, which has a method that is bound to return your instance type; then you can pass the derived JS factory instance into your C++ side and simply call that function instead of the constructor directly.

-- brion

Brion Vibber

unread,
Dec 9, 2015, 4:41:09 PM12/9/15
to emscripten Mailing List
I believe you can avoid the extra factory interface class I mentioned by passing a function that returns the constructed object as an emscripten::val. You can call that, and embind should marshal the object correctly.

So, on the JS side something like:

Module.doSomeStuff(function(f) {
  return new MyDerivedClass(f);
});

on the C++ side something like:

void doSomeStuff(emscripten::val factoryFunc) {
  TestStruct *s = factoryFunc(2.2);
}

-- brion

Joshua Auerbach

unread,
Dec 10, 2015, 4:16:53 AM12/10/15
to emscripte...@googlegroups.com
Well I still could not get it work exactly like this.  I got that conversion from val to work with smart ptrs but not with raw ptrs.

Anyways, I got a workaround that is working well enough, and will stick with that for now.

Thanks for the help.
Reply all
Reply to author
Forward
0 new messages