Wednesday, January 8, 2020

Emscripten - C programs to browser

--- ---

C programs and libraries to Browser

How nice it would be if I can call my own created C programs especially the computational intensive C programs from my Mozilla or Google Browser ( :-) in fact I don’t have anything that much computational intensive), But still . I would also be amazed if I can port some of the C libraries or C++ Games to browser.

Emscripten and Webassembly(wasm) together make this happen

I was following web-assembly and Rust for a few months now. Since Rust has lot of safety features, I did not think of exploring more on porting C or C++ programs to browser.

Emscripten is an Open Source LLVM to JavaScript compiler. Using Emscripten you can:
Compile C and C++ code into JavaScript
Compile any other code that can be translated into LLVM bitcode into JavaScript.
Compile the C/C++ runtimes of other languages into JavaScript, and then run code in those other languages in an indirect way (this has been done for Python and Lua)!

WebAssembly (often shortened to Wasm) is an open standard that defines a portable binary code format for executable programs, and a corresponding textual assembly language, as well as interfaces for facilitating interactions between such programs and their host environment.



Emscripten Installation


Emcripten is not that complex to install,there is good documentation in the site - Emscripten
You might need to install python2.7 and cmake etc as a prior requisite.We just need to follow the instructions. My Linux machine helped me to install everything with apt-get insall command.
You might come across some installation errors, but just search those errors in google, there will be solution to fix it.


C program to wasm


I wrote a simple C program called emccwasm.c
#include<stdio.h>
#include<stdlib.h>
#include<string.h>
#include<stdint.h>
int main(){
        int a = 1;
        printf("%d",a);
        //string function to put a space in the screen
        puts(" ");
        printf("First C program compiled to browser. a=%d",a);
        return 1;
}

In command line, you might need to use below command to compile if you are using Linux machine.
emcc -s NO_EXIT_RUNTIME=1 -s FORCE_FILESYSTEM=1 -s EXPORTED_FUNCTIONS=[’_main’] -o emccwasm.html emccwasm.c
Emscripten FAQ might help you understand these options and resolve the errors you might encounter quickly.
The above command generated 3 files for me , they are emccwasm.html , emccwasm.js and emccwasm.wasm


Emscripten generated Files.


Emcripten created a compiled webassembly file which is emccwasm.wasm as mentioned earlier.Filename will be same as the C program file name. To know more about webassembly , following documentation link helps - https://webassembly.org/
In a nutshell “WebAssembly (abbreviated Wasm) is a binary instruction format for a stack-based virtual machine. Wasm is designed as a portable target for compilation of high-level languages like C/C++/Rust, enabling deployment on the web for client and server application
The .js and .html files are glue files created for web. The html file can be rendered to the browser and Javascript file initialize webassembly and rest of the glue work


http server


You might need to install http server to void below error . The following documentation can be used for installation -
https://github.com/thecoshman/http
Note: if you have installed Cargo in your machine, the server installation will be very easy.
"**Failed to execute ‘compile’ on ‘WebAssembly’: Incorrect response MIME type. Expected ‘application/wasm’.
**
We can run the server simply by below command:


http

Emscripten files in localhost


Once the http server is up, the files will be served in the browser in the link: http://localhost:8000/emccwasm.html
Note: the port might vary .
If everything goes well, you should be getting a screen similar to below.

enter image description here


Accessing exported functions.


When we compiled the C program we used EXPORT_FUNCTIONS option with _main. That means the _main function should be available in Module.
ie , we can invoke main function by Module._main()
enter image description here