IDL signature for a function that returns std::vector<double>

447 views
Skip to first unread message

Philipp Gloor

unread,
Oct 25, 2016, 5:39:15 PM10/25/16
to emscripten-discuss
I have a C++ function that should return a vector of doubles but on the WebIDL doc page I found nothing that could help me.

The header file:

#ifndef __JSAPI_H__
#define __JSAPI_H__

#include <string>
#include "annotation.h"

class JSAPI
{
    Annotation* annotations;
public:
    char* getAnnotContent(int annotID);
    std::vector<double> getAnnotRect(int annotID);

};

#endif

And the implementation

#include "jsapi.h"


char* JSAPI::getAnnotContent(int annotID)
{
    return annotations[annotID].content;
}

std::vector<double> JSAPI::getAnnotRect(int annotID)
{
    return annotations[annotID].rect;
}

And I'm looking for the proper definition of

interface JSAPI
{
    void JSAPI();
    DOMString getAnnotContent(long annotID);
    std::vector<double> getAnnotRect(long annotID);
};

Is something like this even possible? Or do I need to switch to embind for this?

Alon Zakai

unread,
Oct 25, 2016, 6:11:25 PM10/25/16
to emscripten-discuss
Yes, WebIDL focuses on simple types that map directly to JS (numbers, pointers, etc). embind has more functionality for sophisticated mappings of C++ classes, like std::vector.

--
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.

Philipp Gloor

unread,
Oct 26, 2016, 1:32:22 AM10/26/16
to emscripte...@googlegroups.com
​OK thanks. And did I understand correctly that pointers only work for non-primitive data types?​

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.

--
You received this message because you are subscribed to a topic in the Google Groups "emscripten-discuss" group.
To unsubscribe from this topic, visit https://groups.google.com/d/topic/emscripten-discuss/18GjJeGOq08/unsubscribe.
To unsubscribe from this group and all its topics, send an email to emscripten-discuss+unsub...@googlegroups.com.

Alon Zakai

unread,
Oct 26, 2016, 1:37:06 PM10/26/16
to emscripten-discuss
It depends what you mean. A pointer in emscripten (in general) is just an integer. So it's fine to pass pointers into and out of compiled code, including WebIDL glue. The WebIDL glue does add functionality on top, by converting a return value of a wrapped class into a JS object wrapper. It also handles an input parameter that is a JS object wrapper, converting it into the integer for the compiled method underneath (it's also fine to just pass that integer as a parameter).

To unsubscribe from this group and all its topics, send an email to emscripten-discuss+unsubscribe@googlegroups.com.

For more options, visit https://groups.google.com/d/optout.

--
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.

Philipp Gloor

unread,
Oct 26, 2016, 2:35:45 PM10/26/16
to emscripten-discuss
I see. 
If you have a function that on the C++ side returns a double array, what would be your preferred way to make this accessible in JS? I don't know the length of the array beforehand. 

I played around with EM_ASM_INT. 

    JSHelper fillRandomArray()
    {   
        int len = rand()%10 + 10;
        int pointer = EM_ASM_INT({
            var buffer = Module._malloc($0 * 4); 
            return buffer;
        }, len);
        int* a = (int*)pointer;
        for (int i = 0; i < len-1; i++)
        {
            a[i] = i*3;
        }
        JSHelper js;
        js.pointer = pointer;
        js.length
        return js;
    }

and in my .js file

        var nByte = 4;
        var charByte = 1;
        var jsInfo = Module.fillRandomArray();
        var buffer = jsInfo.pointer;
        for (var i = 0; i < jsInfo.length; i++)
        {
            console.log(Module.getValue(buffer + i*nByte, 'i32'));
        }

This works but this seems a bit too complicated for something (seemingly) simple. I've also tried a version where I return just a std::vector which works just fine but our C++ code base tries to avoid using STL for some reasons. Is this a reasonable solution?
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.

--
You received this message because you are subscribed to a topic in the Google Groups "emscripten-discuss" group.
To unsubscribe from this topic, visit https://groups.google.com/d/topic/emscripten-discuss/18GjJeGOq08/unsubscribe.
To unsubscribe from this group and all its topics, send an email to emscripten-discuss+unsub...@googlegroups.com.

For more options, visit https://groups.google.com/d/optout.

Alon Zakai

unread,
Oct 26, 2016, 2:45:10 PM10/26/16
to emscripten-discuss
Yeah, that's close to how I'd do it, when writing for performance (otherwise, embind might be more concise).

You can replace the EM_ASM_INT with a direct call to malloc, though.

And instead of getValue, accessing the typed array directly is much faster (Module.HEAP32[buffer + i*nByte >> 2], note that you need to do the >>2 yourself manually).

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.

--
You received this message because you are subscribed to a topic in the Google Groups "emscripten-discuss" group.
To unsubscribe from this topic, visit https://groups.google.com/d/topic/emscripten-discuss/18GjJeGOq08/unsubscribe.
To unsubscribe from this group and all its topics, send an email to emscripten-discuss+unsubscribe@googlegroups.com.

For more options, visit https://groups.google.com/d/optout.

--
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+unsubscribe@googlegroups.com.

For more options, visit https://groups.google.com/d/optout.

Philipp Gloor

unread,
Oct 26, 2016, 3:19:00 PM10/26/16
to emscripte...@googlegroups.com
You mean embind in combination with using std::vector?

And you mention I have to use >>2 myself. I know that if byteSize == 4 then doing a right bit shift operator divides the value it shifts by 2 but why is this necessary? 

Thanks for your answers and help, it is really much appreciated.

To unsubscribe from this group and all its topics, send an email to emscripten-discuss+unsub...@googlegroups.com.

Alon Zakai

unread,
Oct 26, 2016, 3:41:07 PM10/26/16
to emscripten-discuss
Yes, embind has support for things like std::vector, I believe, so together it might have nice syntax for this.

The reason for the shift is that HEAP32 is a JavaScript typed array, whose elements are 32-bit integers. So if the underlying buffer is [x0, x1, x2, x3, ...] (where those are bytes) then HEAP32[0] accesses the first four of those as a single 32-bit integer. HEAP32[1] accesses x4,x5,x6,x7 and so forth. So if ptr is the address in memory, say 4, then to load a 32-bit integer at address 4 we need to do HEAP32[1], which is the same as HEAP32[4>>2]. So ptr >> 2 is what we want.

To unsubscribe from this group and stop receiving emails from it, send an email to emscripten-discuss+unsub...@googlegroups.com.
Reply all
Reply to author
Forward
0 new messages