javascript - asm.js Module.ccall / Module.cwrap callback -
i have callback functions in c++ want recreate in javascript after compiling emscripten.
anyone knows how call using ccall or cwrap?
thank you!
the technique used convert pointer unsigned int (technically, uint32_t), passed js. when ready callback, passed value c++, converted function pointer, , called associated function.
a lot of can automated; example can setup callback class have base class of pointers converted before virtual function called redirects correct derived class (in case, use handle parameter , return types).
i'm happy out code. i'm working project called empirical header-only library geared toward porting scientific software web. it's still under active , development, might find pieces useful.
https://github.com/mercere99/empirical
emp::jswrap() function takes in std::function object , returns uint32_t.  can find definition here: https://github.com/mercere99/empirical/blob/master/emtools/jswrap.h  should correctly handle basic parameter , return types , std::string, i'm working expand that.  if you're grabing files out of project, note jswrap include few others, not many.
the other relevant file need worry library_emp.js (https://github.com/mercere99/empirical/blob/master/emtools/library_emp.js), defines emp.callback(), can used on js side.
to integrate both of these files program, need to:
- add c++ code 
#include "jswrap.h",#include "init.h"(possibly additional path information) - add compilation: 
--js-library ../../emtools/library_emp.js - before use callbacks, run 
emp::initialize();on c++ side. - wrap function using calling 
uint32_t fun_id = emp::jswrap(functiontobewrapped);return function id value can pass js. alternatively, can calluint32_t fun_id = emp::jswrap(functiontobewrapped, "js_function_name");, create js function specified name. - from js, can either provide specified function id triggering callback 
emp.callback(id, parameters)-or- can use provided name if used 1emp.js_function_name(parameters...), call original function. return value passed back. 
let me know if helps! there documentation @ top of jswrap.h, , test files @ https://github.com/mercere99/empirical/tree/master/utests/emtools (including makefile, code file called jswrap.cc, , html file called jswrap.html).
edit: below example code sends pointer of function object js, , calls js.
#include <emscripten.h> #include <functional>  // couple of possible callbacks, same signature. double times2(double val) { return val * 2; } double plus7(double val) { return val + 7; }  // function callback js takes callback id , arg , callback. extern "c" {   double callback_dd(uint32_t cb_id, double val) {     auto * fun_ptr = reinterpret_cast<std::function<double(double)>*>(cb_id);     return (*fun_ptr)(val);   } }  int main() {   // pick function want run   auto fun = std::function<double(double)>(times2);   // auto fun = std::function<double(double)>(plus7);    // convert function pointer uint32_t.   // note double casting first convert number , reduce 32-bits.   // using reintepret_cast better, looked confusing double cast.   uint32_t cb_id = (uint32_t) (long long) &fun;    // following code passed callback id javascript.  js code uses   // id call original function.   em_asm_args({       callback_dd = module.cwrap('callback_dd', 'number', ['number']);       var x = 12.5;       alert('result: fun(' + x + ') = ' + callback_dd($0, x));     }, cb_id);  }   note if going callback after main() has ended, need make sure functions calling persist.
to compile code, put in file (let's call callback_test.cc) , command line run:
em++ -s exported_functions="['_callback_dd', '_main']" -std=c++11 callback_test.cc -o callback_test.html   you should able open callback_test.html in web browser , call js whichever c++ function pointer passed it.
in case need know function signature ahead of time, mentioned above can use more elaborate callback can remember signature.
Comments
Post a Comment