best way to define message from javascript to emscripten

25 views
Skip to first unread message

Alessio Mochi

unread,
Nov 8, 2022, 10:16:49 AM11/8/22
to emscripten-discuss
Hello, 
I want define some data struct as message and send from emscripten to javascript and viceversa, because i need to comunicate between opengl canvas (on c++ side) to html gui.
What's the best way to do that?

Dieter Weidenbrück

unread,
Nov 8, 2022, 11:09:47 AM11/8/22
to emscripten-discuss
Hi,

I am using this method:

on the JS side allocate a buffer to store things

export class Central {
    constructor(app){
        this.mApp    = app;
        this.trainBuf    = malloc(2048); //or whatever you need
    }

//a function to fill the buffer
sendData(a,b,c){
        let i = this.trainBuf >> 2;
        HEAPF32[ i + 0]  = a;
        HEAPF32[ i + 1]  = b;
        HEAPF32[ i + 2]  = c;
     //sendMessage neds to exist on the C side, too
    sendMessage(this.trainBuf); //inform you c code that data has been sent
    }
};

Then in the c code you accept the event like this:

typedef struct {
    int a,b,c;
}myStruct,*myStructPtr;

myStruct    d;

int sendMessage(void* param){
    myStructPtr    p = (myStructPtr)param;

    d.a    = p->a;
    d.b    = p->b;
    d.c    = p->c;

Dieter Weidenbrück

unread,
Nov 9, 2022, 6:20:02 AM11/9/22
to emscripten-discuss
sorry, the struct should contain floats:

typedef struct {
    float a,b,c;
}myStruct,*myStructPtr;

Alessio Mochi

unread,
Nov 9, 2022, 12:08:18 PM11/9/22
to emscripten-discuss
thank you very much the example works.
I have two question:

if I want send a c struct to javascript how can do it? For example the same data struct 

typedef struct {
    float a,b,c;
}myStruct,*myStructPtr;

question number 2:
in preview example who and when can free this memory? 
this.trainBuf    = malloc(2048);

Thanks in advance

Dieter Weidenbrück

unread,
Nov 9, 2022, 1:26:57 PM11/9/22
to emscripten-discuss
I allocate the buffer at startup time and keep it around for all kinds of messages. So there is always a buffer available to send data back and forth. The same buffer can be used for different data structs.

To access the buffer from C you can store the pointer to it in a local variable, e.g.

#define msgInit 0
#define msgMyStruct 1
void *trainBuf = 0L;

int sendMessage(int msgType, void* param){
  switch (msgType){
    case msgInit:
      trainBuf = param;
      break;
    case msgMyStruct:
      //see above
      break;
  }

So at init time you allocate the buffer on the js side, then send a msgInit to store the pointer (which is an int only) in a local variable. From there on you can use it from both sides:

int msgToJS(float a, float b, float c){
  myStructPtr    p = (myStructPtr)trainBuf;
    p->a    = a;
    p->b    = b;
    p->c    = c;
  //then you notify the JS side:
#ifdef __EMSCRIPTEN__
            EM_ASM_({
//whatever you want to do there. The data will be in central.trainBuf and can be extracted the same way you inserted it when sending the message.
          
           });
#endif //__EMSCRIPTEN__

Regarding your second question:
As said, I keep this buffer alive because I'm sending lots of data back and forth. But of course, you can free the buffer as soon as you have read its contents every time.
Reply all
Reply to author
Forward
0 new messages