Accessing a string from C coming from a promise

144 views
Skip to first unread message

photos...@gmail.com

unread,
May 22, 2021, 2:42:36 PM5/22/21
to emscripten-discuss
I'm quite new to combining C and JavaScript and I'm having trouble seeing how I can possibly access a string in C (on the WASM heap) made as a result of a promise. Here's the function I have so far:

EM_JS(void, em_enumerate_av_devices, (),
{
navigator.mediaDevices.enumerateDevices()
.then(function(devices) {
var str="";
devices.forEach( function(device) { str += device.kind + " \"" + device.label + "\" id = " + device.deviceId + "\n"; });
var c_str = js_string_to_c_string(str); // this is the C string on the WASM heap I'm trying to access in C, I don't know what to do with it
})
.catch(function(err) { console.log(err.name + ": " + err.message); });
});

I need c_str to somehow be accessed from my C code, but how?

Another smaller problem is the function it relies on, js_string_to_c_string(), which is as follows:

function js_string_to_c_string(js_string)
{
var len = lengthBytesUTF8(js_string) + 1;
var c_string = _malloc(len);
stringToUTF8(js_string, c_string, len);
return c_string;
}

I tried putting the whole thing inside an EM_ASM block, but the compiler didn't like that and I haven't seen anyone else use EM_ASM for entire functions. It would make sense to put such utility functions in one .js file, but I can't see how to make emcc include that .js file anywhere (ideally it would include the whole thing into myproject.js like it already does with required files such as runtime_safe_heap.js and others).

Thanks in advance,

Michel Rouzic

Sam Clegg

unread,
May 26, 2021, 12:45:38 AM5/26/21
to emscripte...@googlegroups.com
To add your `js_string_to_c_string` library function you should put it in library JS file and include its via `--js-library` command line.  See https://emscripten.org/docs/porting/connecting_cpp_and_javascript/Interacting-with-code.html#implement-c-in-javascript.

You will likely need to explicitly include `js_string_to_c_string` in `-sDEFAULT_LIBRARY_FUNCS_TO_INCLUDE` because the dependency within `em_enumerate_av_devices` is not a direct one.  If you were calling the JS function directly you it would be included automatically.    For that reason you might want to move em_enumerate_av_devices into the JS library too.. and the you can make the dependency explicitly by adding `em_enumerate_av_devices__deps: ['js_string_to_c_string']`.

In terms of getting the string back to native code one option would be to export a C function and call it from `em_enumerate_av_devices`.  e.g. `var c_str = js_string_to_c_string(str); _my_c_function(c_str)` and then pass `-s EXPORTED_FUNCTION=_my_c_function` at link time.

cheers,
sam

--
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.
To view this discussion on the web visit https://groups.google.com/d/msgid/emscripten-discuss/25fbd314-f1c7-4192-bf7a-71e1558a258bn%40googlegroups.com.

Floh

unread,
May 27, 2021, 6:30:11 AM5/27/21
to emscripten-discuss
If the  js_string_to_c_string() function is only called from that one place I would put it right into the em_enumerate_av_devices() function as a local function similar to what I do here:


To pass a JS string to a C function you can use the automatic marshalling in the ccall() helper function. For instance here I'm getting a JS string from the clipboard and pass it to a C function:


...and the C function simply looks like this (make sure to copy the string data, because AFAIK the original data will be freed after the C function returns:

Reply all
Reply to author
Forward
0 new messages