I'm trying to get started compiling to WebAssembly from C++ and am generally following along with this guide as to how to pass image data to WASM code. I've looked through a handful of other posts, but I'm still fairly lost. Whenever I try to call a function that looks at the data from JS I get errors like: missing function: _Z6getMatPdii
(the function name seems to depend on what type of data I'm creating). For concreteness the relevant bits of code are:
imageRead.cpp:
#include <armadillo>
#include <stdlib.h>
using namespace std;
using namespace arma;
extern "C" {
double* create_buffer(int width, int height) {
return (double *)malloc(width * height * sizeof(double));
}
}
extern "C" {
void destroy_buffer(double* p) {
free(p);
}
}
extern "C" {
mat getMat(double* p, int width, int height) {
return mat(p, height, width); // Armadillo constructor for matrix already in memory
}
}
and the HTML:
var Module = {
...
onRuntimeInitialized: function() {
// API for preparing image transfers:
api = {
create_buffer: Module.cwrap('create_buffer','number',['number','number']),
destroy_buffer: Module.cwrap('destroy_buffer','',['number']),
fdtd: Module.cwrap('fdtd_sim',null,['number','number','number']),
};
p = api.create_buffer(img.width, img.height);
Module.HEAP8.set(imageData,p);
...
and finally fdtd_2d.cpp:
<header stuff>...
#include js_passing.h // Contains headers for imageRead.cpp functions
void fdtd_sim(double* p, int width, int height) {
arma::mat image = getImage(p, width, height);
...do stuff...
and for compilation:
emcc -o simulation.html obj/fdtd_2d.o obj/imageRead.o -Wall -std=c++14 -Lobj -s USE_SDL=2 -s WASM=1 -s NO_EXIT_RUNTIME=1 -s "EXTRA_EXPORTED_RUNTIME_METHODS=['cwrap']" -s ERROR_ON_UNDEFINED_SYMBOLS=0 -s ALLOW_MEMORY_GROWTH=1 -s SAFE_HEAP=1 -s EMULATE_FUNCTION_POINTER_CASTS=1 -s ASSERTIONS=1 -s "EXPORTED_FUNCTIONS=['_fdtd_sim','_create_buffer','_destroy_buffer']" -O2 -I /path/to/armadillo-code/include -lsuperlu_51 -DARMA_DONT_USE_WRAPPER
As in the MDN example above, I'm getting image data from a <canvas>
element which is all working fine, but whenever I try to call getMat
the code fails with the missing function: _Z6getMatPdii
error. I've essentially copied the MDN code so I'm a little baffled as to why it's failing.
On compilation, there is an output that _Z6getMatPdii
is undefined, but I can't figure out where that function is coming from. Also, I've seen other versions of it, e.g. _Z8getImgPhii
(when I was using CImg to try and read the image data).
So, my question is: what's going on here? It clearly seems to be an issue with referencing pointers, but if anything I'm guessing that some library isn't being included correctly and so the constructor functions aren't present when they should be. If there's a better way to be doing this, I'm all ears. The final output I'm trying to achieve is an arma::mat
that has the grayscale image data from the canvas
element. How I get to there is open to interpretation.