Navigation Menu

Skip to content

Instantly share code, notes, and snippets.

@carlopi
Last active December 1, 2020 15:23
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save carlopi/c36e9b8f0eaf72c569491fadac331707 to your computer and use it in GitHub Desktop.
Save carlopi/c36e9b8f0eaf72c569491fadac331707 to your computer and use it in GitHub Desktop.
Example of calling of JavaScript code from C++ with Cheerp
/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
#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;
}
"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
}
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