Emscripten: How to read Javascript string in C++?

Created on 9 Apr 2016  Â·  8Comments  Â·  Source: emscripten-core/emscripten

I tried duplicating this issue but without success.

I also tried returing just the address of the memory and then read from it in C++

--------------------------------------------------------------------------- js
write_string_to_heap: function(_string_dest_in_c){

        var str = "Hello from JS.";
        var buffer = Module._malloc(str.length + 1);
        Module.writeStringToMemory(str, buffer);
        console.log(getValue(buffer, 'i8'));
        Module.ccall('get_js_string', 'null',['string'], [_string_dest_in_c, buffer]);

        /*socket.on("message", function(message){
            return message.message_content;
        });*/
      },
    });
--------------------------------------------------------------------------- cpp
  EMSCRIPTEN_KEEPALIVE
  extern void get_js_string(char* _string_dest, int _string)
  {
    uintptr_t p = _string;
    char* _sstring = reinterpret_cast<char *>(p);
    _string_dest = _sstring;
  };

but still I get weird symbols and not the target string.

How do I send a javascript string to C++ and actually read it and manipulate it?


I also tried this :

extern "C" {
  extern void send_string_to_js_server(const char* flat_board);
  extern void write_string_to_heap(char* _string_dest);
  extern void get_js_string_utf(); 

  EMSCRIPTEN_KEEPALIVE
  extern void printStr(char* dest, char* str)
  {
    std::cout << str << std::endl;
    dest = str;
  }
}

int main()
{
 char *dst;
 get_js_string_utf(dst);
 std::cout << dst << std::endl;

return 0;
}

----------------------------------------------------------js
mergeInto(LibraryManager.library, {
      get_js_string_utf: function(dest)
      {
        Module.ccall('printStr', 'null',['string'], ["Hiiiiii"]);
      },
    });

This does not work, however when I do this:

char* global_variable;
extern "C" {
  extern void send_string_to_js_server(const char* flat_board);
  extern void write_string_to_heap(char* _string_dest);
  extern void get_js_string_utf(); 

  EMSCRIPTEN_KEEPALIVE
  extern void printStr( char* str)
  {
    std::cout << str << std::endl;
    global_variable = str;
  }
}

int main()
{
 get_js_string_utf();
 std::cout << global_variable << std::endl;

return 0;
}

----------------------------------------------------------js
mergeInto(LibraryManager.library, {
      get_js_string_utf: function(dest)
      {
        Module.ccall('printStr', 'null',['string'], ["Hiiiiii"]);
      },
    });

this works!

I wonder why.

wontfix

Most helpful comment

yeah, otherwise it will not return new value. but still you can simplify it in this case

extern "C" char* write_string_to_heap();
write_string_to_heap: function(){
        var str = "Hello from JS.";
        var buffer = Module._malloc(str.length + 1);
        Module.writeStringToMemory(str, buffer);
        return buffer;
    }

All 8 comments

Option 1.
write_string_to_heap: function(_string_dest_in_c) {
    Module.ccall('get_js_string', 'null',['number','string'], [_string_dest_in_c, "Hello from JS."]);
}

Option 2.
write_string_to_heap: function(_string_dest_in_c){
        var str = "Hello from JS.";
        var buffer = Module._malloc(str.length + 1);
        Module.writeStringToMemory(str, buffer);
        Module.ccall('get_js_string', 'null',['number','number'], [_string_dest_in_c, buffer]);
    }


extern "C" void write_string_to_heap(char* s1);
extern "C" void EMSCRIPTEN_KEEPALIVE get_js_string(char* s1, char* s2) {
    printf("%s\n%s\n", s1, s2);
};

write_string_to_heap("Test");

in option 1 emscripten does conversion between js string to heap
in option 2 you do conversion between js string to heap and pass a pointer

Thumbs up for the clean answer, and the clear and direct specifications.

However, the very fact of adding two chars to the signature of writing_string_to_heap changes everything.

As I mentioned at the top, when I add only one char to the signature and store the JS string in a glocal c variable, everything works smoothly.

Now mind you, your example works, only under a very specific circumstance.

Let's talk about option 2:

we have

Option 2.
write_string_to_heap: function(_string_dest_in_c){
        var str = "Hello from JS.";
        var buffer = Module._malloc(str.length + 1);
        Module.writeStringToMemory(str, buffer);
        Module.ccall('get_js_string', 'null',['number','number'], [_string_dest_in_c, buffer]);
    }


extern "C" void write_string_to_heap(char* s1);
extern "C" void EMSCRIPTEN_KEEPALIVE get_js_string(char* s1, char* s2) {
   s1 = s2;
   printf("s1: %s\n s2: %s\n", s1, s2);

};

// main
char* _js_string_receiver;
write_string_to_heap(_js_string_receiver);
printf("\n _js_string_receiver has received: %s", _js_string_receiver);
//output
￀���

The values printed inside of get_js_string just correctly, however in main, I get weird symbols printed.

in this case s1 is local copy of a pointer. You need to pass a pointer to a pointer.

extern "C" void write_string_to_heap(char** s1);
extern "C" void EMSCRIPTEN_KEEPALIVE get_js_string(char** s1, char* s2) {
    *s1 = s2;
};

char* s;
write_string_to_heap(&s);

Thank you!

i just used your test case but can guess you don't need a C-function.

write_string_to_heap: function(_string_dest_in_c){
        var str = "Hello from JS.";
        var buffer = Module._malloc(str.length + 1);
        Module.writeStringToMemory(str, buffer);
        setValue(_string_dest_in_c, buffer, '*');
} 

Real clean, dig this.

And writing_string_to_heap will require a char** for _string_dest_in_c ?

Prototype:

extern void writing_string_to_heap(char** _string_dest_in_c);

yeah, otherwise it will not return new value. but still you can simplify it in this case

extern "C" char* write_string_to_heap();
write_string_to_heap: function(){
        var str = "Hello from JS.";
        var buffer = Module._malloc(str.length + 1);
        Module.writeStringToMemory(str, buffer);
        return buffer;
    }

This issue has been automatically marked as stale because there has been no activity in the past 2 years. It will be closed automatically if no further activity occurs in the next 7 days. Feel free to re-open at any time if this issue is still relevant.

Was this page helpful?
0 / 5 - 0 ratings

Related issues

rpellerin picture rpellerin  Â·  3Comments

JCash picture JCash  Â·  3Comments

nerddan picture nerddan  Â·  4Comments

ShawZG picture ShawZG  Â·  4Comments

nemequ picture nemequ  Â·  4Comments