Bien évidemment que cela ne tuera pas JavaScript, les WebAssembly serviront, surtout, à remplacer les plugins natif Netscape et ActiveX qui sont désormais bloqué par les navigateurs !
Je me pose des questions sur l’interopérabilité entre WebAssemblies et l’interpréteur JavaScript ! Car actuellement je galère à porter une librairie C de physiques avec Emscripten, si la compilation ne pose pas de problème (Emscripten et totalement compatible avec gcc ), l’export d’une API utilisable en JavaScript est une entreprise long et fastidieuse.
Il faut bien comprendre que Emscripten ne permet d’exporter que les fonctions avec des signatures simple (avec ccall et cwrap) mais pas les structures et objet (qui en c/c++ sont les mêmes choses). Du coup cela oblige à créer un Wrappeur d’objet JavaScript pour chaque structure.
Pour exemple : voici la définition de la structure Mass :
Je dois donc compter la taille en octet, afin de pouvoir l’allouer sur le tas de la LLVM ici :
Code : Sélectionner tout - Visualiser dans une fenêtre à part
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32 struct dMass { dReal mass; dVector4 c; dMatrix3 I; #ifdef __cplusplus dMass() { dMassSetZero (this); } void setZero() { dMassSetZero (this); } void setParameters (dReal themass, dReal cgx, dReal cgy, dReal cgz, dReal I11, dReal I22, dReal I33, dReal I12, dReal I13, dReal I23) { dMassSetParameters (this,themass,cgx,cgy,cgz,I11,I22,I33,I12,I13,I23); } void setSphere (dReal density, dReal radius) { dMassSetSphere (this,density,radius); } void setCapsule (dReal density, int direction, dReal a, dReal b) { dMassSetCappedCylinder (this,density,direction,a,b); } void setCappedCylinder (dReal density, int direction, dReal a, dReal b) { setCapsule(density, direction, a, b); } void setBox (dReal density, dReal lx, dReal ly, dReal lz) { dMassSetBox (this,density,lx,ly,lz); } void adjust (dReal newmass) { dMassAdjust (this,newmass); } void translate (dReal x, dReal y, dReal z) { dMassTranslate (this,x,y,z); } void rotate (const dMatrix3 R) { dMassRotate (this,R); } void add (const dMass *b) { dMassAdd (this,b); } #endif };
Les réels sont des flottants de simple précision encoder sur 4 octets1 (réel mass) +4 (vecteur c)+ 3*4 (matrice3x4 I ) = 17 réel = 17 * 4 octets
La fonction constructrice d’instance de Mass, exporté en JavaScript, nécessite l’écriture suivante :
Ainsi en javascript il est possible de soit créer une instance de Mass par new ODE.Mass() ; ou de caster une zone mémoire en tant que Mass par new ODE.Mass(pointer) ;
Code : Sélectionner tout - Visualiser dans une fenêtre à part
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37 /************** Mass API *********************/ var sizeOfMass = (1+4+4*3)*4; var dMassSetZero = Module.cwrap('dMassSetZero',null,['number']); var dMassSetParameters = Module.cwrap('dMassSetParameters',null,['number', 'number', 'number', 'number', 'number', 'number', 'number', 'number', 'number', 'number', 'number']); var dMassSetSphere = Module.cwrap('dMassSetSphere',null,['number', 'number', 'number']); var dMassSetSphereTotal = Module.cwrap('dMassSetSphereTotal',null,['number', 'number', 'number']); var dMassSetCapsule = Module.cwrap('dMassSetCapsule',null,['number', 'number', 'number', 'number', 'number']); var dMassSetCapsuleTotal = Module.cwrap('dMassSetCapsuleTotal',null,['number', 'number', 'number', 'number', 'number']); var dMassSetCylinder = Module.cwrap('dMassSetCylinder',null,['number', 'number', 'number', 'number', 'number']); var dMassSetCylinderTotal = Module.cwrap('dMassSetCylinderTotal',null,['number', 'number', 'number', 'number', 'number']); var dMassSetBox = Module.cwrap('dMassSetBox',null,['number', 'number', 'number', 'number', 'number']); var dMassSetBoxTotal = Module.cwrap('dMassSetBoxTotal',null,['number', 'number', 'number', 'number', 'number']); var dMassAdjust = Module.cwrap('dMassAdjust',null,['number', 'number']); var dMassTranslate = Module.cwrap('dMassTranslate',null,['number', 'number', 'number', 'number']); var dMassRotate = Module.cwrap('dMassRotate',null,['number', 'number']); var dMassAdd = Module.cwrap('dMassAdd',null,['number', 'number']); ODE.Mass = function () { var pointer = arguments[0] || Module._malloc(sizeOfMass); this.getPointer = function() { return pointer;} this.destroy = function() { return Module._free(pointer); } this.setZero = function() { dMassSetZero(pointer); return this;} this.setParameters = function( mass,cgx, cgy, cgz, I11, I22, I33, I12, I13, I23) { dMassSetParameters(pointer, mass,cgx, cgy, cgz, I11, I22, I33, I12, I13, I23); return this;} this.setSphere = function(density, radius) { dMassSetSphere(pointer,density, radius); return this;} this.setSphereTotal = function(total_mass, radius) { dMassSetSphereTotal(pointer,total_mass, radius); return this;} this.setCapsule = function(density, direction, a, b) { dMassSetCapsule(pointer, density, direction, a, b); return this;} this.setCapsuleTotal = function(total_mass, direction, a, b) { dMassSetCapsuleTotal(pointer, total_mass, direction, a, b); return this;} this.setCylinder = function(density, direction, a, b) { dMassSetCylinder(pointer, density, direction, a, b); return this;} this.setCylinderTotal = function(total_mass, direction, a, b) { dMassSetCylinderTotal(pointer, total_mass, direction, a, b); return this;} this.setBox = function(density, lx, ly, lz) { dMassSetBox(pointer, density, lx, ly, lz); return this;} this.setBoxTotal = function(total_mass, lx, ly, lz) { dMassSetBoxTotal(pointer, total_mass, lx, ly, lz); return this;} this.adjust = function(newmass) { dMassAdjust(pointer, newmass); return this;} this.translate = function(x,y,z) { dMassTranslate(pointer, x,y,z); return this;} this.rotate = function(rotation) { dMassRotate(mass, rotation.getPointer()); return this;} this.add = function(mass) { dMassAdd(pointer, mass.getPointer()); return this;} }
Mais cela peut encore se complexifier, en effet les données membre de la structure ne sont pas exposer a l’objet JavaScript, pour cela il faut donc ajouter ceci au constructeur Mass :
De plus un problème persiste avec cette méthode de wrapping, en effet ces feignasses de scripteurs ( dont je fais partie ), non pas pour habitude de se poser des question à propos de la gestion Mémoire. Or ici il est nécessaire d’appeler la méthode destroy avant la collecte du ramasse miettes, afin d’éviter tous Memory leak …
Code : Sélectionner tout - Visualiser dans une fenêtre à part
1
2
3
4
5
6
7
8 Object.defineProperty(this,"mass",{ enumerable : true, get : function(){ return Module.getValue(pointer,'float');}, set : function(val) { Module.setValue(pointer,val,'float'); } }); this.c = new ODE.Vector4(pointer+4); this.I = new ODE.Matrix3(pointer+4+4*4);
Bref je vous laisse estimer le tempe qu’il faut pour exporter l’API d’une librairie c/c++ … et j’ai bien peur que tous ce travail soit à pure perte pour un futur export WebAssembly
Partager