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 :ccool: ), l’export d’une API utilisable en JavaScript est une entreprise long et fastidieuse. :aie:
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:
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 octetsCitation:
1 (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:
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:
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 :calim2: