Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How do I pass objects from Javascript to C++ using Emscripten

I want to pass back a Javascript object from JS to C++ class/method. I have the following simple code snippet which is not working:

// Access JS objects in C++ like C++ objects

#include "emscripten/val.h"   //Causing errors !

using namespace emscripten;
int main() {
    val Math = val::global("Math");
    return Math.call("abs", -10); // returns 10
}

I use the following to compile using emscripten on windows :

cmd> emcc Access_Objects.cpp

I get huge log of errors :

In file included from Access_Objects.cpp:2:
In file included from C:\Program Files\Emscripten\emscripten\1.16.0\system\inclu
de\emscripten/val.h:4:
C:\Program Files\Emscripten\emscripten\1.16.0\system\include\emscripten/wire.h:2
4:5: error:
      unknown type name 'constexpr'
    constexpr bool has_unbound_type_names = true;
    ^
C:\Program Files\Emscripten\emscripten\1.16.0\system\include\emscripten/wire.h:2
4:15: error:
      expected unqualified-id
    constexpr bool has_unbound_type_names = true;
              ^
C:\Program Files\Emscripten\emscripten\1.16.0\system\include\emscripten/wire.h:5
6:21: error:
      use of undeclared identifier 'has_unbound_type_names'
                if (has_unbound_type_names || std::is_polymorphic<C>::value) {
                    ^
C:\Program Files\Emscripten\emscripten\1.16.0\system\include\emscripten/wire.h:6
7:17: error:
      use of undeclared identifier 'has_unbound_type_names'
            if (has_unbound_type_names || std::is_polymorphic<C>::value) {
                ^
C:\Program Files\Emscripten\emscripten\1.16.0\system\include\emscripten/wire.h:8
2:40: error:
      a space is required between consecutive right angle brackets (use '> >')
        struct TypeID<std::unique_ptr<T>> {
                                       ^
C:\Program Files\Emscripten\emscripten\1.16.0\system\include\emscripten/wire.h:9
8:42: error:
      a space is required between consecutive right angle brackets (use '> >')
        struct TypeID<AllowedRawPointer<T>> {
                                         ^
C:\Program Files\Emscripten\emscripten\1.16.0\system\include\emscripten/wire.h:1
82:9: error:
      unknown type name 'constexpr'
        EMSCRIPTEN_DEFINE_NATIVE_BINDING_TYPE(char);
        ^
C:\Program Files\Emscripten\emscripten\1.16.0\system\include\emscripten/wire.h:1
74:13: note:
      expanded from macro 'EMSCRIPTEN_DEFINE_NATIVE_BINDING_TYPE'
            constexpr static WireType toWireType(const type& v) {   \
            ^
C:\Program Files\Emscripten\emscripten\1.16.0\system\include\emscripten/wire.h:1
82:9: error:
      expected member name or ';' after declaration specifiers
        EMSCRIPTEN_DEFINE_NATIVE_BINDING_TYPE(char);
        ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
C:\Program Files\Emscripten\emscripten\1.16.0\system\include\emscripten/wire.h:1
74:23: note:
      expanded from macro 'EMSCRIPTEN_DEFINE_NATIVE_BINDING_TYPE'
            constexpr static WireType toWireType(const type& v) {   \
            ~~~~~~~~~ ^
C:\Program Files\Emscripten\emscripten\1.16.0\system\include\emscripten/wire.h:1
83:9: error:
      unknown type name 'constexpr'
        EMSCRIPTEN_DEFINE_NATIVE_BINDING_TYPE(signed char);
        ^
C:\Program Files\Emscripten\emscripten\1.16.0\system\include\emscripten/wire.h:1
74:13: note:
      expanded from macro 'EMSCRIPTEN_DEFINE_NATIVE_BINDING_TYPE'
            constexpr static WireType toWireType(const type& v) {   \
            ^
C:\Program Files\Emscripten\emscripten\1.16.0\system\include\emscripten/wire.h:1
83:9: error:
      expected member name or ';' after declaration specifiers
        EMSCRIPTEN_DEFINE_NATIVE_BINDING_TYPE(signed char);
        ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
C:\Program Files\Emscripten\emscripten\1.16.0\system\include\emscripten/wire.h:1
74:23: note:
      expanded from macro 'EMSCRIPTEN_DEFINE_NATIVE_BINDING_TYPE'
            constexpr static WireType toWireType(const type& v) {   \
            ~~~~~~~~~ ^
C:\Program Files\Emscripten\emscripten\1.16.0\system\include\emscripten/wire.h:1
84:9: error:
      unknown type name 'constexpr'
        EMSCRIPTEN_DEFINE_NATIVE_BINDING_TYPE(unsigned char);
        ^
C:\Program Files\Emscripten\emscripten\1.16.0\system\include\emscripten/wire.h:1
74:13: note:
      expanded from macro 'EMSCRIPTEN_DEFINE_NATIVE_BINDING_TYPE'
            constexpr static WireType toWireType(const type& v) {   \
            ^
C:\Program Files\Emscripten\emscripten\1.16.0\system\include\emscripten/wire.h:1
84:9: error:
      expected member name or ';' after declaration specifiers
        EMSCRIPTEN_DEFINE_NATIVE_BINDING_TYPE(unsigned char);
        ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
C:\Program Files\Emscripten\emscripten\1.16.0\system\include\emscripten/wire.h:1
74:23: note:
      expanded from macro 'EMSCRIPTEN_DEFINE_NATIVE_BINDING_TYPE'
            constexpr static WireType toWireType(const type& v) {   \
            ~~~~~~~~~ ^
C:\Program Files\Emscripten\emscripten\1.16.0\system\include\emscripten/wire.h:1
85:9: error:
      unknown type name 'constexpr'
        EMSCRIPTEN_DEFINE_NATIVE_BINDING_TYPE(signed short);
        ^
C:\Program Files\Emscripten\emscripten\1.16.0\system\include\emscripten/wire.h:1
74:13: note:
      expanded from macro 'EMSCRIPTEN_DEFINE_NATIVE_BINDING_TYPE'
            constexpr static WireType toWireType(const type& v) {   \
            ^
C:\Program Files\Emscripten\emscripten\1.16.0\system\include\emscripten/wire.h:1
85:9: error:
      expected member name or ';' after declaration specifiers
        EMSCRIPTEN_DEFINE_NATIVE_BINDING_TYPE(signed short);
        ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
C:\Program Files\Emscripten\emscripten\1.16.0\system\include\emscripten/wire.h:1
74:23: note:
      expanded from macro 'EMSCRIPTEN_DEFINE_NATIVE_BINDING_TYPE'
            constexpr static WireType toWireType(const type& v) {   \
            ~~~~~~~~~ ^
C:\Program Files\Emscripten\emscripten\1.16.0\system\include\emscripten/wire.h:1
86:9: error:
      unknown type name 'constexpr'
        EMSCRIPTEN_DEFINE_NATIVE_BINDING_TYPE(unsigned short);
        ^
C:\Program Files\Emscripten\emscripten\1.16.0\system\include\emscripten/wire.h:1
74:13: note:
      expanded from macro 'EMSCRIPTEN_DEFINE_NATIVE_BINDING_TYPE'
            constexpr static WireType toWireType(const type& v) {   \
            ^
C:\Program Files\Emscripten\emscripten\1.16.0\system\include\emscripten/wire.h:1
86:9: error:
      expected member name or ';' after declaration specifiers
        EMSCRIPTEN_DEFINE_NATIVE_BINDING_TYPE(unsigned short);
        ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
C:\Program Files\Emscripten\emscripten\1.16.0\system\include\emscripten/wire.h:1
74:23: note:
      expanded from macro 'EMSCRIPTEN_DEFINE_NATIVE_BINDING_TYPE'
            constexpr static WireType toWireType(const type& v) {   \
            ~~~~~~~~~ ^
C:\Program Files\Emscripten\emscripten\1.16.0\system\include\emscripten/wire.h:1
87:9: error:
      unknown type name 'constexpr'
        EMSCRIPTEN_DEFINE_NATIVE_BINDING_TYPE(signed int);
        ^
C:\Program Files\Emscripten\emscripten\1.16.0\system\include\emscripten/wire.h:1
74:13: note:
      expanded from macro 'EMSCRIPTEN_DEFINE_NATIVE_BINDING_TYPE'
            constexpr static WireType toWireType(const type& v) {   \
            ^
C:\Program Files\Emscripten\emscripten\1.16.0\system\include\emscripten/wire.h:1
87:9: error:
      expected member name or ';' after declaration specifiers
        EMSCRIPTEN_DEFINE_NATIVE_BINDING_TYPE(signed int);
        ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
C:\Program Files\Emscripten\emscripten\1.16.0\system\include\emscripten/wire.h:1
74:23: note:
      expanded from macro 'EMSCRIPTEN_DEFINE_NATIVE_BINDING_TYPE'
            constexpr static WireType toWireType(const type& v) {   \
            ~~~~~~~~~ ^
C:\Program Files\Emscripten\emscripten\1.16.0\system\include\emscripten/wire.h:1
88:9: error:
      unknown type name 'constexpr'
        EMSCRIPTEN_DEFINE_NATIVE_BINDING_TYPE(unsigned int);
        ^
C:\Program Files\Emscripten\emscripten\1.16.0\system\include\emscripten/wire.h:1
74:13: note:
      expanded from macro 'EMSCRIPTEN_DEFINE_NATIVE_BINDING_TYPE'
            constexpr static WireType toWireType(const type& v) {   \
            ^
fatal error: too many errors emitted, stopping now [-ferror-limit=]
20 errors generated.
ERROR    root: compiler frontend failed to generate LLVM bitcode, halting

The error is being caused in 'wire.h' which is included in 'emscripten/val.h'.

How do I resolve these errors? Or Is there any other way to pass objects from JS to C++ ?

like image 861
FacePalm Avatar asked Jul 02 '14 07:07

FacePalm


People also ask

How do I translate JavaScript code to C++ using Emscripten?

Embind provides a C++ class, emscripten::val, which you can use to transliterate JavaScript code to C++. Using val you can call JavaScript objects from your C++, read and write their properties, or coerce them to C++ values like a bool, int, or std::string. The example below shows how you can use val to call the JavaScript Web Audio API from C++:

How do I use Emscripten with inline JavaScript?

EM_ASM is used in a similar manner to inline assembly code. The “alert” example might be written with inline JavaScript as: When compiled and run, Emscripten will execute the two lines of JavaScript as if they appeared directly in the generated code. The result would be an alert, followed by an exception.

What is Emscripten_run_script ()?

Emscripten provides numerous methods to connect and interact between JavaScript and compiled C or C++: Call compiled C functions from normal JavaScript: Using ccall or cwrap. Using direct function calls (faster but more complicated). Call JavaScript functions from C/C++: Using emscripten_run_script().

How do I export a function from Emscripten?

1 Exporting is done at compile time. ... 2 Note that you need _ at the beginning of the function names in the EXPORTED_FUNCTIONS list. 3 Note that _main is mentioned in that list. ... 4 Emscripten does dead code elimination to minimize code size — exporting ensures the functions you need aren’t removed. More items...


1 Answers

There are other ways to interact between JS and C++. The most stable way that I've found is to build your own library by wrapping JS functions so that you can call them from C++.

If you want to call Javascript's Math.abs() from C++, you can edit "src/library.JS". In there you'll find a giant map of function names that are available in C++. If you wanted to call your new function "JS_Math_abs", you would add:

JS_Math_abs: function(value) {
  return Math.abs(value);
},

Then you would modify your C++ code to specify input and output types. Add:

extern "C" {
  extern int JS_Math_abs(int);
}

Don't get me wrong, this method is more annoying than val should be (were it working properly), but it should also be more efficient in the end. Once you have the main libraries you need wrapped, you'll find it's very stable. For the most part, however, it's easy to use the C++ versions of functions like abs().

You can find out more about creating your own libraries here: http://kripken.github.io/emscripten-site/docs/porting/connecting_cpp_and_javascript/Interacting-with-code.html#interacting-with-code-call-javascript-from-native

like image 69
Charles Ofria Avatar answered Sep 24 '22 02:09

Charles Ofria