Playing with low-level memory in WebAssembly – DEV Community

admin

I wrote a [blog post](https://dev.to/iprosk/my-first-take-on-webassembly-213h) about my first experience with WebAssembly (WASM) recently.An in that post, I touched a little bit how to set up an SDK for writing code in C/C++, and how to compile a simple C++ function that can take couple of numbers values from JavaScript, run WASM binary in a browser,…

I wrote a [blog post](https://dev.to/iprosk/my-first-take-on-webassembly-213h) about my first experience with WebAssembly (WASM) recently.An in that post, I touched a little bit how to set up an SDK for writing code in C/C++, and how to compile a simple C++ function that can take couple of numbers values from JavaScript, run WASM binary in a browser, and return a value.For those who just jumped in, WebAssembly is cool cross-platform binary format, assembly language, and a Virtual Machine to run this binary inside a browser.What can it do? Well, it [can mine crypto currency](https://www.zdnet.com/article/half-of-the-websites-using-webassembly-use-it-for-malicious-purposes/) inside while you browse you favorite webpages.And guess who pays for the electricity? Well, besides crypto-currency abuse, it is an interesting technology to run heavy stuff client-side with reasonable performance.[ ](#where-to-start) Where to start I am playing around with [Emscipten](https://emscripten.org) which wraps around clang to compile C/C++ code in WASM binary and provide some glue-code API to embed WASM binary into JavaScript.

Look into [MDN Docs](https://developer.mozilla.org/en-US/docs/WebAssembly) and [Emscripten SDK](https://emscripten.org/docs/getting_started/index.html) to get started.[ ](#managing-memory-with-emscripten) Managing memory with Emscripten Before, diving into high-level Emscripten stuff such as [Embind](https://emscripten.org/docs/porting/connecting_cpp_and_javascript/embind.html?highlight=embind), I decided to look into its low-level memory model.Here is a toy problem.We have a C-function that takes an array of double, do something with them and return a number.It may look as simple this.// malloc_testing.c #include #include #include double vector_norm(double* p, int n) { int i; double norm2 = 0; assert(n > 0 && “number of elements must be positive”); assert(p && “must be a valid pointer”); printf(“received: n = %dn”, n); for (i = 0; i Run Here, I first create a JavaScript typed array with float64 continuous view of memory.

After that, I create an empty buffer on the heap inside WASM memory by calling to _malloc that we exported when we compiled our C-file.It returns a pointer buf to the allocated segment of memory, which in JavaScript code is treated simply as a number (very “safe”, eh?).Next step is to fill allocated memory with something.I use Module.HEAPF64.set(myTypedArray, buf / myTypedArray.BYTES_PER_ELEMENT) that takes two argument: my array, and a pointer to the buffer.Note the alignment! In this case, the pointer must count by 8-bytes.It actually took me more than an hour to figure it out since Empscipten API docs are quite, hm, emscryptic on this point.

Thanks to ChatGPT and [this post](https://stackoverflow.com/questions/70050802/where-is-the-documentation-for-webassembly-heapf64-set).To see how it works, we can replace the call to HEAPF64.set by manual allocation.I came up with something like this (don’t do it anywhere near production!): function setMemoryManually(myArray, ptr) { for (const x of myArray) { Module.setValue(ptr, x, ‘double’); ptr += myArray.BYTES_PER_ELEMENT; } } It looks terrible, but works.Low-level function Module.setValue(ptr, value, ‘double’) can be used to manually set a value at the address pointed by ptr.In this case, no tricks.The pointer is incremented by BYTES_PER_ELEMENT = 8 for double.

So now I can write something like setMemoryManually(myTypedArray, buf) in my JavaScript code, and it will fill the buffer with the content of myTypedArray.When all memory is set, we can call our C-function from JavaScript.I prefer to wrap up first.const vectorNorm = Module.cwrap(‘vector_norm’, // no underscore ‘number’, // return type [‘number’, ‘number’]); // param types; We tell cwrap that we return a number, and we pass a couple of numbers.Well, yes, the pointer to the buffer of the allocated memory is passed as a number (looks very safe and portable, eh?).So we can just call vectorNorm from our script.const result = vectorNorm(buf, myTypedArray.length); Last step.Open a browser, serve our http-web page from a local host (I just run python -m http.server) http://localhost:8000/wasm_testing/malloc_testing.html hard reload, press Run, and here we go received: n = 5 p[0] = 0.000 p[1] = 1.000 p[2] = 2.000 p[3] = 3.000 p[4] = 5.000 result = 6.244997998398398 [ ](#in-summary) In summary…

Playing with low-level stuff is fun, but I won’t use it anywhere in productionable code.Well, at least without considerable experience and understanding of the [Emscripten code base](https://github.com/emscripten-core/emscripten)..

Leave a Reply

Next Post

Mastercard Included (MA) Presents at Goldman Sachs Communacopia & Know-how Convention (Transcript) – Future Insight

Mastercard Included (NYSE:MA) Goldman Sachs Communacopia & Know-how Convention September 5, 2023 5:25 PM ET Firm Members Michael Miebach – Chief Government Officer Convention Name Members William Nance – Goldman Sachs William Nance All proper.I feel we’ll get began right here.Thanks everybody for becoming a member of us.My title is Will Nance, I cowl funds…
Mastercard Included (MA) Presents at Goldman Sachs Communacopia & Know-how Convention (Transcript) – Future Insight

Subscribe US Now