Opérations de structure en Javascript via Emscripten

Je rencontre pas mal de problèmes d’interaction entre emscripten et C et C

Plus précisément, je ne parviens pas à accéder à une structure créée en C en javascript, étant donné que le pointeur sur la structure est passé à javascript en tant que bibliothèque externe .

Regardez le code suivant:

C:

#include  #include  #include  struct test_st; extern void read_struct(struct test_st *mys, int siz); struct test_st{ uint32_t my_number; uint8_t my_char_array[32]; }; int main(){ struct test_st *teststr = malloc(sizeof(struct test_st)); teststr->my_number = 500; for(int i = 0; i my_char_array[i] = 120 + i; } for(int i = 0; i my_char_array[i]); } read_struct(teststr,sizeof(teststr)); return 0; } 

Javascript:

 mergeInto(LibraryManager.library, { read_struct: function(mys,siz){ var read_ptr = 0; console.log("my_number: " + getValue(mys + read_ptr, 'i32')); read_ptr += 4; for(var i = 0; i < 32; i++){ console.log("my_char[" + i + "]: " + getValue(mys + read_ptr, 'i8')); read_ptr += 1; }; }, }); 

Ceci est ensuite compilé en utilisant emcc cfile.c --js-library jsfile.js .

Le problème ici est que vous ne pouvez pas vraiment lire les structures en javascript, vous devez obtenir de la mémoire à partir des adresses respectives en fonction de la taille du champ struct (lisez donc 4 octets dans uint32_t et 1 octet dans uint8_t). Ok, ce ne serait pas un problème, sauf que vous devez également indiquer le type IR de LLVM pour que getValue fonctionne. Il n’inclut pas les types non signés. Ainsi, dans le cas du tableau, il passera à 127 et débordera à -128, lorsque le comportement prévu est de continuer à monter, car la variable est non signée.

J’ai cherché partout une réponse, mais apparemment, ce comportement spécifique n’est pas courant. Changer la structure ne serait pas possible dans le programme auquel j’applique ceci (pas l’exemple ci-dessus).

Une solution consiste à utiliser les tableaux typés HEAP* exposés par Emscripten, qui ont des vues non signées:

 mergeInto(LibraryManager.library, { read_struct: function(myStructPointer, size) { // Assumes the struct starts on a 4-byte boundary var myNumber = HEAPU32[myStructPointer/4]; console.log(myNumber); // Assumes my_char_array is immediately after my_number with no padding var myCharArray = HEAPU8.subarray(myStructPointer+4, myStructPointer+4+32); console.log(myCharArray); } }); 

Cela fonctionne dans mon test, en exécutant Emscripten 1.29.0-64bit, mais comme indiqué, il repose sur des hypothèses concernant l’alignement / le remplissage. Les cas que j’ai testés semblaient montrer qu’une structure semblait toujours commencer par une limite de 4 octets et que des entiers non signés 32 bits à l’intérieur d’une structure étaient également toujours alignés sur une limite de 4 octets, et donc accessibles par HEAPU32.

Cependant, je ne sais pas si vous pouvez compter sur ce comportement dans Emscripten. Je crois comprendre que vous ne pouvez pas dans le monde habituel du C / C ++.