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