Passing JS ArrayBuffer to C via ccall

610 views
Skip to first unread message

Floh

unread,
Dec 14, 2016, 11:01:45 AM12/14/16
to emscripten-discuss
Hi,

I can't seem to find example code of how to pass an ArrayBuffer from JS to C via ccall() (for instance, there doesn't seem to be a test for this in the SDK?), and I have problems doing this (the passed data is broken). I'm sure it's something simple...

Background: I want to pass file content data from a JS drag-n-drop event handler to the C side.

What I have on the JS side:

...
// this is the array buffer as result of a FileReader, this contains the
// expected data (I checked through logging the first couple of bytes to the console)
var content = loadEvent.target.result;      

// now the ccall to a C function "emsc_pass_data" with 3 params, a string name, the content, and the length
Module.ccall('emsc_pass_data',
    null,
    ['string', 'array', 'number'],
    [file.name, content, content.byteLength]);
...

...and on the C side I have:

void emsc_pass_data(const char* name, const uint8_t* data, int size) {

}

The function is called, name has a valid string, size is also right, data is some pointer, but the pointed-to data behind the pointers doesn't match the ArrayBuffer content (it looks fairly random with lots of zeros).

What am I doing wrong? I would most appreciate some code example to look at :) 

PS: the emscripten documentation on ccall is a bit hand-wavy on the array type, a small code example there would be very helpful (both the JS and C side), see here: https://kripken.github.io/emscripten-site/docs/api_reference/preamble.js.html#calling-compiled-c-functions-from-javascript

Cheers,
-Floh.

Floh

unread,
Dec 14, 2016, 11:14:39 AM12/14/16
to emscripten-discuss
...and 1 minute later I found the problem by mulling over the ccall source in preamble.js :D

The problem is that I'm passing a raw ArrayBuffer object, when ccall expects an Uint8Array. ArrayBuffer has no .length property, which is expected by ccall.

So the JS side needs to look something like this:

var content = new Uint8Array(loadEvent.target.result);
Module.ccall('emsc_pass_data',
    null,
    ['string', 'array', 'number'],
    [file.name, content, content.length]);

...some more examples in the docs and probably a test for ccall with 'array' would be nice though ;)

Cheers,
-Floh.

Alon Zakai

unread,
Dec 14, 2016, 1:52:58 PM12/14/16
to emscripten-discuss
Adding an assert and a typed array test in https://github.com/kripken/emscripten/pull/4797

As for the docs, they say

> use ``"number"`` for any C pointer, and ``"array"`` for JavaScript arrays and typed arrays; note that arrays are 8-bit

is that not clear enough?

--
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-discuss+unsub...@googlegroups.com.
For more options, visit https://groups.google.com/d/optout.

Floh

unread,
Dec 14, 2016, 4:48:52 PM12/14/16
to emscripten-discuss
At least I was a bit confused by that sentence in the docs ;) I was thinking that on the JS side, data goes in as normal JS arrays (that is clear enough), but I interpreted the 'typed array' as a generic ArrayBuffer object, and thought that the note about 8-bit arrays is about how the data arrives on the C side (as an array of bytes, regardless of what type the items in the ArrayBuffer are).

I think it would be better if the docs mention the JS class name Uint8Array somewhere (and of course a small code sample would be even better).

Alon Zakai

unread,
Dec 14, 2016, 6:58:59 PM12/14/16
to emscripten-discuss
Ah ok, it might be the usual JS confusion then, an ArrayBuffer is not an array. I added a commit specifying it must be a Uint8Array or Int8Array.

To unsubscribe from this group and stop receiving emails from it, send an email to emscripten-discuss+unsubscribe@googlegroups.com.

For more options, visit https://groups.google.com/d/optout.
Reply all
Reply to author
Forward
0 new messages