📜 ⬆️ ⬇️

Back to the future with WebAssembly

Hi, Habr! I present to you the translation of the article “Back To The Future With WebAssembly” by Attila Vágó.

This post is a translation of the article, which describes the properties of WebAssemly and Emscripten. Original article in English.


The author of the article, Attila Vago, is a senior software developer at HMH. Writes code, blogs and stuff on the Internet. A polyglot of programming languages, a pragmatic leader, with a passion for JavaScript and easy access. An easily inspired and inspiring person with a strong passion for nerds, great food, craft beer and Lego. Uses Mac. Do exercises at 6 in the morning.

In 2011, I wrote my first independent line of code not in HTML (I worked with it in 2007), and it was written in that same good C that Professor David J. Malan from Harvard University taught. He will forever remain my instigator not only in the study of programming, but also in software thinking. I also remembered that making a peanut butter sandwich was just for me, but it’s an incredibly difficult task for a computer and equally difficult for a person pretending to be a computer.



If you watched the video, even the first 18 minutes (I know that it is long, but programming takes time), then you will understand why C is close to my heart to this day. To my disappointment, I never learned it, because let's face it, for web developer C is the smallest of priorities. I never had a real reason to dive deep into this language, despite buying countless Udemy courses and books on C, I never touched them (keep your judgmental views with you, you did as well) or lie to yourself that if I buy Pebble smart watches, which work on C, I will definitely write a code for them. Yes exactly! None of these reasons were compelling enough.


What is WebAssembly and how does it overtake JS?


WebAssembly (Wasm for short) is a binary instruction format for a stack virtual machine.

“Wasm is designed as a portable platform for compiling high-level languages ​​such as C / C ++ / Rust, which allows you to deploy client and server applications on the Internet.”
- kindly explains webassembly.org


In other words, the above means that you can write modules that work on the Internet, in a browser / server, but are written in languages ​​like C, compiled into a binary file and therefore incredibly fast, as they work directly on the hardware of the machine. Compared to them, scripting languages ​​such as JavaScript have several levels of abstraction between code and hardware, which, among other things, makes them slow. Of course, this does not always matter, and each of them has its place in the program or even the web ecosystem.


On this basis, Wasm's structure (initially) only supports integers and floating-point numbers, which gives more processing power and, therefore, is often used for implementations of the canvas type. It is important to understand that WebAssembly does not pose a threat to JavaScript — at least for now — and, as you will see later in this article, C and JavaScript can actually live very happily in the same project and can run each other’s code. Yes, something like that.


')

Emscripten "sticks together" C and JS


Now hold on! I know what I am saying. You can't say things like running C in JS and vice versa, and expect the world not to react. No matter how strange it may sound, I am not deceiving. It turns out that Emscripten is a chain of tools for compiling in asm.js and WebAssembly, designed using LLVM (oh my god, I learned half of these things while typing the text of the article), which allows you to run C and C ++ on the Internet at almost native speed without plug-ins.


Well, here's what you need to set aside for yourself. Emscripten will help you compile the code written in C in WebAssembly, providing additional tools to ease the burden on the developer when it comes to communication between the two languages, and help launch Wasm in your web project. The basic Emscripten compilation command is as follows:


emcc lib/strings.c -s WASM=1 -o public/strings.js 

While not a basic command runs like this:

 emcc lib/imports.c -s WASM=1 -s EXPORTED_FUNCTIONS="['_getNum', '_main', '_getDoubleNum', '_greet']" -o public/imports.js 

Setting up the Emscripten is not the easiest thing, but it’s not a rocket launch. The only thing that complicates the configuration is that it has many dependencies, such as Python, Node, xCode, Git and cMake. All instructions can be found on the installation page and easy to follow.
Therefore Emscripten:


Note: You do not need Emscripten to generate Wasm, because an API is built into all new browsers to support Wasm in the same window that Emscripten runs as the top layer, which makes the developer’s life much easier. For example, Emscripten will adjust the amount of memory for you, which can be tedious through C.


Examples ... examples are everywhere!


You know, as they say, “a line of code is worth a thousand words ,” OK, this is the narrator’s prerogative and all that, so without further ado let's take a look at some real code. Off-topic comment: I couldn’t overcome the syntax on that day. It didn’t compile half the time because my code would be shaky. And after eight years, I’m like this: “It’s like JavaScript .


Guys, if someone starts to see the C code in my React, just bring me back to reality, okay?


A little off topic, here's a valid C code:


image

And, accordingly, in JavaScript:


image

OK, what exactly is happening in these files? Actually quite a lot, so I will list.

  1. It is important to understand that main () , unless otherwise specified, is always run first and also compiles by default. If you want to compile another function, you will need to specifically set it in the EXPORTED_FUNCTIONS array flag , as shown in the previous section.
  2. You write your C code, as usual, by importing its regular libraries, but on top of this you get Emscripten syntax sugar, as well as more methods / functions than with any other tool.
  3. The imports.js file (the name is arbitrary, but always the same as the C file), referenced by HTML, is nothing more than the “glue” Emscripten, which is automatically generated during compilation. No need to worry about it, just make sure it is really referenced.
  4. Printf is just an ordinary C operator that registers a string on the console. Nothing special, moving on.
  5. Lines 14 and 17 are an anti-pattern, but a good example of running JS in your C code. The only real difference between emscripten_run_script and emscripten_async_run_script is that the latter allows you to run JS in C asynchronously. Basically with setTimeout () . The reason I said that this anti-pattern is because it is. The whole idea of ​​WebAssembly is to run C in JS, not JS in C, and, therefore, ...
  6. Lines 20 and 24 and the associated JS functions in the index.html file represent the correct template, namely, the declaration of your JS in your JS and the return of something for C.
  7. EM_JS , which then runs jsFunction , is simply a simpler way — to achieve a similar goal, as in points 4 and 5.

The predictable result of the above is:


image

Ladies First!


As with any code, WebAssembly also has an execution order. Do not mess with the queue! The order in this case is standard for C order. Everything runs in Main () and whenever main () is ready, ready and wasm. However, what happens if you need a static function to call at run time? Well, just a little Emscripten syntax sugar, and everything goes like clockwork:


image

We collect flies from the cake


This is well-written code, especially the simple things illustrated in the previous sections, but we all know that the real world is much more than “Hello World”, and half of each developer’s time is spent figuring out why the code doesn’t do what should. Bugs are simply inevitable and in some sense are part of life.


When you run C in JS or any Wasm, for that matter, everything can become even more depressing. Fortunately, Emscripten comes to the rescue again by providing two very useful debugging methods:


 // browser debugger gets triggered emscripten_debugger(); // browser console warning with stack-trace emscripten_log(EM_LOG_WARN, “'param' your message”); 

Fast Gonzalez hurries to help


Believe it or not, the creators of Emscripten have thought of everything. One big feature - and the last one, which I will mention in this article, since there are too many of them to put them all in one - is the basis for rapid development and testing. You can compile your Wasm, build a project and start the server in one fell swoop:


 emrun --port 7777 --no_browser public/index.html Now listening at http://localhost:7777/ 

The html page you are running is not emrun-capable. Stdout, stderr and exit (returncode) capture will not work. Recompile the program with the flag to enable this, or pass it’s a way to hide this check.

Well, two swings ... the example above works, but the next one works better, which is explained by the error.


 <b>// compile as emrun project emcc lib/strings.c -s WASM=1 --emrun -o public/index.html // run the emrun server again emrun --port 7777 --no_browser public/index.html</b> 

I'll just leave it like that. Studying WebAssembly, I celebrated St. Patrick's Day and the next day. Not quite sure what will happen next, but it worried me enough to sit in front of the monitor for two days, trying to penetrate the basics of WebAssebly, and that should mean something, right? This is the most C code that I have written since 2011, and it feels great. I think WebAssembly has a real future, but I'm not sure that it will completely capture the network and kill JS, as some people preach. And what do you think?


image

Source: https://habr.com/ru/post/453008/


All Articles