Last active
December 1, 2020 15:23
-
-
Save carlopi/c36e9b8f0eaf72c569491fadac331707 to your computer and use it in GitHub Desktop.
Example of calling of JavaScript code from C++ with Cheerp
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
/opt/cheerp/bin/clang++ example.cpp -o example.js -O3 -cheerp-pretty-code | |
#WebAssembly is the default target | |
#-cheerp-pretty-code is not needed, but the resulting code is more readable for this example purposes |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#include <cmath> | |
namespace client | |
{ | |
//Function defined in the namespace client are only forward declared | |
//and have to be defined in the JavaScript side | |
//This is the same mechanism that allows to forward declare any browsers APIs | |
double getRandomNumber(); | |
}; | |
void [[cheerp::genericjs]] printEstimatedAverageAndStdDev(double mean, double stdDev) | |
{ | |
//This is a "regular" C++ function that the attribute [[cheerp::genericjs]] forces to be compiled to JavaScript | |
//The __asm__ keyworld allows to directly "inject" JavaScript code | |
//With strong requirements on the types involved, it can also take input/output | |
//See more details here: https://github.com/leaningtech/cheerp-meta/wiki/JavaScript-interoperability#the-_asm_-keyword | |
__asm__("console.log('Estimated average = ', %0);" :: "r" (mean)); | |
__asm__("console.log('Estimated standard deviation = ', %0);" :: "r" (stdDev)); | |
} | |
int main() | |
{ | |
double sum = 0.0; | |
double sum2 = 0.0; | |
double n = 0; | |
for (int i=0; i<1e6; i++) | |
{ | |
double x = client::getRandomNumber(); | |
sum += x; | |
sum2 += x*x; | |
n += 1.0; | |
} | |
const double average = sum / n; | |
const double variance = sum2 / n - average * average; | |
const double stdDev = sqrt(variance); | |
printEstimatedAverageAndStdDev(average, stdDev); | |
return 0; | |
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
"use strict"; | |
/*Compiled using Cheerp (R) by Leaning Technologies Ltd*/ | |
var __imul=Math.imul; | |
var __fround=Math.fround; | |
var oSlot=0;var nullArray=[null];var nullObj={d:nullArray,o:0}; | |
function fetchBuffer(p){ | |
var b=null,f='function'; | |
if(typeof fetch===f)b=fetch(p).then(r=>r.arrayBuffer()); | |
else if(typeof require===f){ | |
p=require('path').join(__dirname, p); | |
b=new Promise((y,n)=>{ | |
require('fs').readFile(p,(e,d)=>{ | |
if(e)n(e); | |
else y(d); | |
}); | |
}); | |
}else b=new Promise((y,n)=>{ | |
y(read(p,'binary')); | |
}); | |
return b; | |
} | |
function __Z30printEstimatedAverageAndStdDevdd(Lmean,LstdDev){ | |
console.log('Estimated average = ', Lmean);; | |
console.log('Estimated standard deviation = ', LstdDev);; | |
} | |
function assignHeaps(Ldiv){ | |
} | |
var __asm=null,__heap=null;function __dummy(){throw new Error('this should be unreachable');}; | |
__dummy.promise= | |
fetchBuffer('example.wasm').then(Ldiv=> | |
WebAssembly.instantiate(Ldiv, | |
{i:{ | |
__Z30printEstimatedAverageAndStdDevdd:__Z30printEstimatedAverageAndStdDevdd, | |
__ZN6client15getRandomNumberEv:getRandomNumber, | |
}}) | |
).then(Ldiv=>{ | |
__asm=Ldiv.instance.exports; | |
__heap=__asm.memory.buffer; | |
assignHeaps(__heap); | |
__asm._main(); | |
}); | |
/////////////END OF FILE////////////// | |
function getRandomNumber() | |
{ | |
//This function has to be implemented separately, is not part of the output | |
return Math.random(); | |
//or try with -> return 7.0; | |
//or whatever, this is just JS, so feel free to call any function | |
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
module | |
(type (;0;) (func (param f64 f64))) | |
(type (;1;) (func (result f64))) | |
(type (;2;) (func)) | |
(type (;3;) (func (result i32))) | |
(import "i" "__ZN6client30printEstimatedAverageAndStdDevEdd" (func (;0;) (type 0))) | |
(import "i" "__ZN6client15getRandomNumberEv" (func (;1;) (type 1))) | |
(func $__wasm_nullptr (type 2) | |
unreachable) | |
(func $main (type 3) (result i32) | |
(local i32 f64 f64 f64 f64) | |
i32.const 0 | |
global.get 1 | |
local.tee 2 | |
local.tee 3 | |
local.set 4 | |
local.set 0 | |
loop ;; label = @1 | |
local.get 0 | |
i32.const 1 | |
i32.add | |
local.tee 0 | |
call 1 | |
local.tee 1 | |
local.get 2 | |
f64.add | |
local.set 2 | |
local.get 3 | |
local.get 1 | |
local.get 1 | |
f64.mul | |
f64.add | |
local.set 3 | |
local.get 4 | |
f64.const 0x1p+0 (;=1;) | |
f64.add | |
local.set 4 | |
i32.const 1000000 | |
i32.ne | |
br_if 0 (;@1;) | |
end | |
local.get 2 | |
local.get 4 | |
f64.div | |
local.tee 2 | |
local.get 3 | |
local.get 4 | |
f64.div | |
local.get 2 | |
local.get 2 | |
f64.mul | |
f64.sub | |
f64.sqrt | |
call 0 | |
i32.const 0) | |
(table (;0;) 1 anyfunc) | |
(memory (;0;) 17 128) | |
(global (;0;) (mut i32) (i32.const 1048576)) | |
(global (;1;) f64 (f64.const 0x0p+0 (;=0;))) | |
(export "memory" (memory 0)) | |
(export "_main" (func $main)) | |
(elem (;0;) (i32.const 0) $__wasm_nullptr)) |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment