<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:dc="http://purl.org/dc/elements/1.1/">
  <channel>
    <title>DEV Community: Dario Castañé</title>
    <description>The latest articles on DEV Community by Dario Castañé (@dcc).</description>
    <link>https://dev.to/dcc</link>
    <image>
      <url>https://media2.dev.to/dynamic/image/width=90,height=90,fit=cover,gravity=auto,format=auto/https:%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Fuser%2Fprofile_image%2F19686%2F95426058-9d13-4bee-b655-29aacf8f9e15.jpg</url>
      <title>DEV Community: Dario Castañé</title>
      <link>https://dev.to/dcc</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/dcc"/>
    <language>en</language>
    <item>
      <title>Hello world from a WASM module in a static binary</title>
      <dc:creator>Dario Castañé</dc:creator>
      <pubDate>Sat, 22 Feb 2025 12:27:38 +0000</pubDate>
      <link>https://dev.to/dcc/hello-world-from-a-wasm-module-in-a-static-binary-m5k</link>
      <guid>https://dev.to/dcc/hello-world-from-a-wasm-module-in-a-static-binary-m5k</guid>
      <description>&lt;p&gt;These are some quick notes documenting a Saturday morning's experiment. All the steps were executed on Linux.&lt;/p&gt;

&lt;h2&gt;
  
  
  TL;DR: What?
&lt;/h2&gt;

&lt;p&gt;Compiling a static binary that runs a compiled Ahead-of-Time (AOT) WASM module.&lt;/p&gt;

&lt;p&gt;Ideally it'd have been WASM bytecode compiled to native code, but I couldn't find a way that didn't rely on the WASM runtime, invoking it from the command line or embedded in a C program.&lt;/p&gt;

&lt;h2&gt;
  
  
  Why?
&lt;/h2&gt;

&lt;p&gt;I've been &lt;a href="https://bsky.app/profile/did:plc:aj77r5uwt72o6oimdjfplqoz/post/3ligzkt3d5k2m" rel="noopener noreferrer"&gt;thinking&lt;/a&gt; and &lt;a href="https://bsky.app/profile/dario.cat/post/3lir4hjn3g226" rel="noopener noreferrer"&gt;learning&lt;/a&gt; this week about WebAssembly and its potential since I read &lt;a href="https://creston.blog/wasm-will-replace-containers/" rel="noopener noreferrer"&gt;"WASM will replace containers"&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;I decided initially to use &lt;a href="https://wasmer.io/" rel="noopener noreferrer"&gt;Wasmer&lt;/a&gt; and ended filing a &lt;a href="https://github.com/wasmerio/wasmer/issues/5422" rel="noopener noreferrer"&gt;question on their repository&lt;/a&gt; because their own native binary build command doesn't work as expected.&lt;/p&gt;

&lt;p&gt;Finally, I landed on Bytecode Alliance's &lt;a href="https://github.com/bytecodealliance/wasm-micro-runtime" rel="noopener noreferrer"&gt;WebAssembly Micro Runtime (WAMR)&lt;/a&gt; &lt;code&gt;wamrc&lt;/code&gt; compiler.&lt;/p&gt;

&lt;h2&gt;
  
  
  How?
&lt;/h2&gt;

&lt;h3&gt;
  
  
  The code
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;(module
  ;; Import the required WASI functions
  (import "wasi_snapshot_preview1" "fd_write" (func $fd_write (param i32 i32 i32 i32) (result i32)))

  ;; Define a buffer to store the message
  (memory (export "memory") 1)
  (data (i32.const 8) "Hello, World!\n")

  ;; Define the _start function
  (func $main (export "_start")
    ;; Setup the iovec array
    (i32.store (i32.const 0) (i32.const 8))    ;; pointer to the message
    (i32.store (i32.const 4) (i32.const 14))   ;; length of the message

    ;; Call fd_write
    (call $fd_write
      (i32.const 1)  ;; file_descriptor - 1 for stdout
      (i32.const 0)  ;; *iovs - pointer to the iovec array
      (i32.const 1)  ;; iovs_len - number of iovec entries
      (i32.const 20) ;; nwritten - where to store the number of bytes written
    )
    drop ;; Discard the result
  )
)
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This is WebAssembly Text. Learn more &lt;a href="https://developer.mozilla.org/en-US/docs/WebAssembly/Guides/Understanding_the_text_format" rel="noopener noreferrer"&gt;here&lt;/a&gt;.&lt;/p&gt;

&lt;h3&gt;
  
  
  The tools
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;&lt;a href="https://github.com/WebAssembly/wabt" rel="noopener noreferrer"&gt;wat2wasm&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://github.com/WebAssembly/binaryen" rel="noopener noreferrer"&gt;wasm-opt&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://github.com/bytecodealliance/wasm-micro-runtime/tree/main/wamr-compiler" rel="noopener noreferrer"&gt;wamrc&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Everything had to be compiled from scratch.&lt;/p&gt;

&lt;p&gt;&lt;code&gt;wasm-opt&lt;/code&gt; isn't really required, so I'll skip it. I learnt about it while looking at these &lt;a href="https://00f.net/2023/01/04/webassembly-benchmark-2023/" rel="noopener noreferrer"&gt;benchmarks&lt;/a&gt;, and I want these notes to keep track of the interesting tidbits I discovered.&lt;/p&gt;

&lt;h3&gt;
  
  
  The process
&lt;/h3&gt;

&lt;p&gt;First, let's generate WASM bytecode from our WebAssembly Text code:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;wat2wasm ./hello_world.wat &lt;span class="nt"&gt;-o&lt;/span&gt; ./hello_world.wasm
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Next, compile it:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;wamrc &lt;span class="nt"&gt;--format&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;aot &lt;span class="nt"&gt;-o&lt;/span&gt; ./hello_world.aot ./hello_world.wasm
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;For the last step, we need some C glue to embed the WAMR runtime:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight c"&gt;&lt;code&gt;&lt;span class="cp"&gt;#include&lt;/span&gt; &lt;span class="cpf"&gt;&amp;lt;stdio.h&amp;gt;&lt;/span&gt;&lt;span class="cp"&gt;
#include&lt;/span&gt; &lt;span class="cpf"&gt;&amp;lt;stdlib.h&amp;gt;&lt;/span&gt;&lt;span class="cp"&gt;
#include&lt;/span&gt; &lt;span class="cpf"&gt;&amp;lt;string.h&amp;gt;&lt;/span&gt;&lt;span class="cp"&gt;
#include&lt;/span&gt; &lt;span class="cpf"&gt;"wasm_export.h"&lt;/span&gt;&lt;span class="c1"&gt;  // Now points to WAMR's core/iwasm/include/&lt;/span&gt;&lt;span class="cp"&gt;
#include&lt;/span&gt; &lt;span class="cpf"&gt;"hello_world.h"&lt;/span&gt;&lt;span class="cp"&gt;
&lt;/span&gt;
&lt;span class="c1"&gt;// Define a static pool buffer with proper alignment&lt;/span&gt;
&lt;span class="cp"&gt;#define POOL_SIZE (256 * 1024)  // 256 KB pool
&lt;/span&gt;&lt;span class="k"&gt;static&lt;/span&gt; &lt;span class="kt"&gt;uint8_t&lt;/span&gt; &lt;span class="n"&gt;global_pool_buf&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;POOL_SIZE&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="n"&gt;__attribute__&lt;/span&gt;&lt;span class="p"&gt;((&lt;/span&gt;&lt;span class="n"&gt;aligned&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;8&lt;/span&gt;&lt;span class="p"&gt;)));&lt;/span&gt;  &lt;span class="c1"&gt;// 8-byte alignment&lt;/span&gt;

&lt;span class="kt"&gt;int&lt;/span&gt; &lt;span class="nf"&gt;main&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="n"&gt;RuntimeInitArgs&lt;/span&gt; &lt;span class="n"&gt;init_args&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="n"&gt;memset&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="o"&gt;&amp;amp;&lt;/span&gt;&lt;span class="n"&gt;init_args&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="k"&gt;sizeof&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;RuntimeInitArgs&lt;/span&gt;&lt;span class="p"&gt;));&lt;/span&gt;

    &lt;span class="c1"&gt;// Configure memory pool&lt;/span&gt;
    &lt;span class="n"&gt;init_args&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;mem_alloc_type&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;Alloc_With_Pool&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;  &lt;span class="c1"&gt;// Use pool allocator&lt;/span&gt;
    &lt;span class="n"&gt;init_args&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;mem_alloc_option&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;pool&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;heap_buf&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;global_pool_buf&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="n"&gt;init_args&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;mem_alloc_option&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;pool&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;heap_size&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;sizeof&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;global_pool_buf&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

    &lt;span class="c1"&gt;// Initialize the WAMR runtime&lt;/span&gt;
    &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="o"&gt;!&lt;/span&gt;&lt;span class="n"&gt;wasm_runtime_full_init&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="o"&gt;&amp;amp;&lt;/span&gt;&lt;span class="n"&gt;init_args&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="n"&gt;printf&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"Runtime initialization failed.&lt;/span&gt;&lt;span class="se"&gt;\n&lt;/span&gt;&lt;span class="s"&gt;"&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
        &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;

    &lt;span class="c1"&gt;// Load the AOT module from the embedded blob&lt;/span&gt;
    &lt;span class="kt"&gt;char&lt;/span&gt; &lt;span class="n"&gt;error_buf&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="mi"&gt;128&lt;/span&gt;&lt;span class="p"&gt;];&lt;/span&gt;
    &lt;span class="n"&gt;wasm_module_t&lt;/span&gt; &lt;span class="n"&gt;module&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;wasm_runtime_load&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;hello_world_aot&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;hello_world_aot_len&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;error_buf&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="k"&gt;sizeof&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;error_buf&lt;/span&gt;&lt;span class="p"&gt;));&lt;/span&gt;
    &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="o"&gt;!&lt;/span&gt;&lt;span class="n"&gt;module&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="n"&gt;printf&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"Load failed: %s&lt;/span&gt;&lt;span class="se"&gt;\n&lt;/span&gt;&lt;span class="s"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;error_buf&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
        &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;

    &lt;span class="c1"&gt;// Instantiate the module&lt;/span&gt;
    &lt;span class="n"&gt;wasm_module_inst_t&lt;/span&gt; &lt;span class="n"&gt;inst&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;wasm_runtime_instantiate&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;module&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;65536&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;65536&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;error_buf&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="k"&gt;sizeof&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;error_buf&lt;/span&gt;&lt;span class="p"&gt;));&lt;/span&gt;
    &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="o"&gt;!&lt;/span&gt;&lt;span class="n"&gt;inst&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="n"&gt;printf&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"Failed to instantiate: %s&lt;/span&gt;&lt;span class="se"&gt;\n&lt;/span&gt;&lt;span class="s"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;error_buf&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
        &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;

    &lt;span class="c1"&gt;// Call a function named "main" exported from the WASM module&lt;/span&gt;
    &lt;span class="n"&gt;wasm_function_inst_t&lt;/span&gt; &lt;span class="n"&gt;func&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;wasm_runtime_lookup_function&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;inst&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s"&gt;"_start"&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="o"&gt;!&lt;/span&gt;&lt;span class="n"&gt;func&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="n"&gt;printf&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"Function '_start' not found.&lt;/span&gt;&lt;span class="se"&gt;\n&lt;/span&gt;&lt;span class="s"&gt;"&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
        &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;

    &lt;span class="n"&gt;wasm_exec_env_t&lt;/span&gt; &lt;span class="n"&gt;env&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;wasm_runtime_create_exec_env&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;inst&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;65536&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="o"&gt;!&lt;/span&gt;&lt;span class="n"&gt;env&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="n"&gt;printf&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"Failed to create environment.&lt;/span&gt;&lt;span class="se"&gt;\n&lt;/span&gt;&lt;span class="s"&gt;"&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
        &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;

    &lt;span class="c1"&gt;// Execute the function&lt;/span&gt;
    &lt;span class="n"&gt;wasm_runtime_call_wasm&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;env&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;func&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nb"&gt;NULL&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

    &lt;span class="c1"&gt;// Cleanup&lt;/span&gt;
    &lt;span class="n"&gt;wasm_runtime_deinstantiate&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;inst&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="n"&gt;wasm_runtime_unload&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;module&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="n"&gt;wasm_runtime_destroy&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The sharp reader may be asking "Where are the &lt;code&gt;wasm_export.h&lt;/code&gt; and &lt;code&gt;hello_world.h&lt;/code&gt; includes? The former is in &lt;a href="https://github.com/bytecodealliance/wasm-micro-runtime/tree/main/core/iwasm/include" rel="noopener noreferrer"&gt;&lt;code&gt;wasm-micro-runtime/core/iwasm/include&lt;/code&gt;&lt;/a&gt;, and the later needs to be generated:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;xxd &lt;span class="nt"&gt;-i&lt;/span&gt; hello_world.aot &lt;span class="o"&gt;&amp;gt;&lt;/span&gt; hello_world.h
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;And we can compile and run it:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;gcc &lt;span class="nt"&gt;-static&lt;/span&gt; &lt;span class="nv"&gt;$HOME&lt;/span&gt;/Code/hello-wasm/main.c &lt;span class="nv"&gt;$HOME&lt;/span&gt;/Code/wasm-micro-runtime/product-mini/platforms/linux/build/libiwasm.a &lt;span class="nt"&gt;-lm&lt;/span&gt; &lt;span class="nt"&gt;-I&lt;/span&gt; &lt;span class="nv"&gt;$HOME&lt;/span&gt;/Code/wasm-micro-runtime/core/iwasm/include &lt;span class="nt"&gt;-I&lt;/span&gt; &lt;span class="nv"&gt;$HOME&lt;/span&gt;/Code/hello-wasm &lt;span class="nt"&gt;-o&lt;/span&gt; &lt;span class="nv"&gt;$HOME&lt;/span&gt;/Code/hello-wasm/hello_world

&lt;span class="nv"&gt;$HOME&lt;/span&gt;/Code/hello-wasm/hello_world
Hello, World!
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Note: it's not a perfect statically-linked binary. It depends on &lt;code&gt;getaddrinfo&lt;/code&gt;, but this is better left out of scope right now.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://www.flickr.com/photos/duncan/10165341933" rel="noopener noreferrer"&gt;Image&lt;/a&gt; by Duncan Cumming.&lt;/p&gt;

</description>
      <category>webassembly</category>
    </item>
    <item>
      <title>A portal between Ruby and Go (using FFI)</title>
      <dc:creator>Dario Castañé</dc:creator>
      <pubDate>Tue, 06 Sep 2022 09:48:50 +0000</pubDate>
      <link>https://dev.to/dcc/a-portal-between-ruby-and-go-using-ffi-48gn</link>
      <guid>https://dev.to/dcc/a-portal-between-ruby-and-go-using-ffi-48gn</guid>
      <description>&lt;p&gt;Thinking about migrating some huge REST APIs from Ruby to Go, I researched how to replace the Ruby code progressively with Go code.&lt;/p&gt;

&lt;p&gt;I ended up with a possible FFI-based prototype. The solution is to have the Ruby code load a Go library and wrap the Go functions in Ruby classes and methods.&lt;/p&gt;

&lt;h2&gt;
  
  
  The Ruby side
&lt;/h2&gt;

&lt;p&gt;The Ruby side is pretty straightforward. We must load the Go library and import the Go functions in Ruby classes and methods.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight ruby"&gt;&lt;code&gt;&lt;span class="nb"&gt;require&lt;/span&gt; &lt;span class="s1"&gt;'ffi'&lt;/span&gt;

&lt;span class="k"&gt;module&lt;/span&gt; &lt;span class="nn"&gt;Portal&lt;/span&gt;
  &lt;span class="kp"&gt;extend&lt;/span&gt; &lt;span class="no"&gt;FFI&lt;/span&gt;&lt;span class="o"&gt;::&lt;/span&gt;&lt;span class="no"&gt;Library&lt;/span&gt;

  &lt;span class="n"&gt;ffi_lib&lt;/span&gt; &lt;span class="s1"&gt;'./libexample.so'&lt;/span&gt;

  &lt;span class="k"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;Example&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;&lt;/span&gt; &lt;span class="no"&gt;FFI&lt;/span&gt;&lt;span class="o"&gt;::&lt;/span&gt;&lt;span class="no"&gt;Struct&lt;/span&gt;
    &lt;span class="c1"&gt;# This must be completely in sync with the C struct defined in Go code.&lt;/span&gt;
    &lt;span class="n"&gt;layout&lt;/span&gt; &lt;span class="ss"&gt;:id&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="ss"&gt;:int&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="ss"&gt;:prefix&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="ss"&gt;:pointer&lt;/span&gt;

    &lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;initialize&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;prefix&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nb"&gt;id&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
      &lt;span class="nb"&gt;self&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="ss"&gt;:prefix&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="no"&gt;FFI&lt;/span&gt;&lt;span class="o"&gt;::&lt;/span&gt;&lt;span class="no"&gt;MemoryPointer&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;from_string&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;prefix&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
      &lt;span class="nb"&gt;self&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="ss"&gt;:id&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nb"&gt;id&lt;/span&gt;
    &lt;span class="k"&gt;end&lt;/span&gt;

    &lt;span class="c1"&gt;# This feels convoluted, but it hides the fact that our function is loaded&lt;/span&gt;
    &lt;span class="c1"&gt;# outside of the "struct mirror" class.&lt;/span&gt;
    &lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;greet&lt;/span&gt;
      &lt;span class="no"&gt;Portal&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;greet&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nb"&gt;self&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="k"&gt;end&lt;/span&gt;
  &lt;span class="k"&gt;end&lt;/span&gt;

  &lt;span class="n"&gt;attach_function&lt;/span&gt; &lt;span class="s1"&gt;'greet'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="no"&gt;Example&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;by_value&lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt; &lt;span class="ss"&gt;:void&lt;/span&gt;
&lt;span class="k"&gt;end&lt;/span&gt;

&lt;span class="n"&gt;ex&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="no"&gt;Portal&lt;/span&gt;&lt;span class="o"&gt;::&lt;/span&gt;&lt;span class="no"&gt;Example&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;new&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;'C'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;137&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="n"&gt;ex&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;greet&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  The Go side
&lt;/h2&gt;

&lt;p&gt;The Go side is a bit more complex. We need to define a C-compatible struct and export the functions we want to use from Ruby.&lt;/p&gt;

&lt;p&gt;The cool thing is that we can define the functions with the struct as the receiver.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight go"&gt;&lt;code&gt;&lt;span class="k"&gt;package&lt;/span&gt; &lt;span class="n"&gt;main&lt;/span&gt;

&lt;span class="c"&gt;/*
struct example {
    int ID;
    char *Prefix;
};
*/&lt;/span&gt;
&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="s"&gt;"C"&lt;/span&gt;
&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="s"&gt;"fmt"&lt;/span&gt;

&lt;span class="c"&gt;// This declaration is just an alias to the C struct.&lt;/span&gt;
&lt;span class="k"&gt;type&lt;/span&gt; &lt;span class="n"&gt;Example&lt;/span&gt; &lt;span class="n"&gt;C&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;struct_example&lt;/span&gt;

&lt;span class="c"&gt;//export greet&lt;/span&gt;
&lt;span class="k"&gt;func&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;e&lt;/span&gt; &lt;span class="n"&gt;Example&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="n"&gt;greet&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="n"&gt;fmt&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Printf&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"Hello from %s-%d&lt;/span&gt;&lt;span class="se"&gt;\n&lt;/span&gt;&lt;span class="s"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;C&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;GoString&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;e&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Prefix&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt; &lt;span class="n"&gt;e&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;ID&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="k"&gt;func&lt;/span&gt; &lt;span class="n"&gt;main&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  The build
&lt;/h2&gt;

&lt;p&gt;The build is also straightforward. We need to:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Compile the Go code to a shared library. This command will generate the CGO bindings.&lt;/li&gt;
&lt;li&gt;Run the Ruby code.
&lt;/li&gt;
&lt;/ol&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;go build &lt;span class="nt"&gt;-buildmode&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;c-shared &lt;span class="nt"&gt;-o&lt;/span&gt; libexample.so example.go
ruby portal.rb
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  The result
&lt;/h2&gt;

&lt;p&gt;If we run the code, we get the following output:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;Hello from C-137&lt;/p&gt;
&lt;/blockquote&gt;

&lt;h2&gt;
  
  
  The benefits
&lt;/h2&gt;

&lt;p&gt;The main benefit of this approach is that we can progressively migrate the Ruby code to Go. We can start by replacing part by part, until we are ready to switch to a pure Go service.&lt;/p&gt;

&lt;p&gt;It's not only possible to replace existing Ruby code. Now we can reuse RSpec/Minitest specs to test the new Go code. Instead of going for a full rewrite with no tests, we can start by testing the new code with the existing ones.&lt;/p&gt;

&lt;h2&gt;
  
  
  The (possible) drawbacks
&lt;/h2&gt;

&lt;p&gt;Performance-wise this approach is not ideal. We are adding a layer of indirection. This probably adds some overhead to the calls. This is something we need to measure if applied to high-traffic services.&lt;/p&gt;

</description>
      <category>ruby</category>
      <category>go</category>
      <category>ffi</category>
    </item>
    <item>
      <title>Simple Deno HTTP server running in Nanos unikernel</title>
      <dc:creator>Dario Castañé</dc:creator>
      <pubDate>Wed, 25 Aug 2021 21:11:15 +0000</pubDate>
      <link>https://dev.to/dcc/simple-deno-http-server-running-in-nanos-unikernel-2e3f</link>
      <guid>https://dev.to/dcc/simple-deno-http-server-running-in-nanos-unikernel-2e3f</guid>
      <description>&lt;p&gt;This short post shows how to get a &lt;a href="https://deno.land/manual@v1.13.2/tools/compiler"&gt;self-executable&lt;/a&gt; Deno HTTP server to run in &lt;a href="https://nanos.org/"&gt;Nanos&lt;/a&gt; using &lt;a href="https://nanovms.gitbook.io/ops/basic_usage#build-and-deploy-nanos-unikernel"&gt;Ops&lt;/a&gt;.&lt;/p&gt;

&lt;h2&gt;
  
  
  The server
&lt;/h2&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;port&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nb"&gt;Number&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;Deno&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;env&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="kd"&gt;get&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;PORT&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;));&lt;/span&gt;
&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;listener&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;Deno&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;listen&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt; &lt;span class="na"&gt;port&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;port&lt;/span&gt; &lt;span class="p"&gt;});&lt;/span&gt;

&lt;span class="nx"&gt;console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;log&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;`http://localhost:&lt;/span&gt;&lt;span class="p"&gt;${&lt;/span&gt;&lt;span class="nx"&gt;port&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;`&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

&lt;span class="k"&gt;for&lt;/span&gt; &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;conn&lt;/span&gt; &lt;span class="k"&gt;of&lt;/span&gt; &lt;span class="nx"&gt;listener&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="k"&gt;async&lt;/span&gt; &lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;requests&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;Deno&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;serveHttp&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;conn&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="k"&gt;for&lt;/span&gt; &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;respondWith&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;of&lt;/span&gt; &lt;span class="nx"&gt;requests&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
      &lt;span class="nx"&gt;respondWith&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nx"&gt;Response&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;Hello world&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;));&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;
  &lt;span class="p"&gt;})();&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Compilation and local deployment
&lt;/h2&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;deno compile &lt;span class="nt"&gt;--allow-env&lt;/span&gt; &lt;span class="nt"&gt;--allow-net&lt;/span&gt; hello.ts
ops run &lt;span class="nt"&gt;-e&lt;/span&gt; &lt;span class="nv"&gt;HOME&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;/ &lt;span class="nt"&gt;-e&lt;/span&gt; &lt;span class="nv"&gt;PORT&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;8000 &lt;span class="nt"&gt;-p&lt;/span&gt; 8000 hello
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The trick is to set the HOME variable. It can have any value, but &lt;code&gt;/&lt;/code&gt; feels right.&lt;/p&gt;

&lt;h2&gt;
  
  
  Summary
&lt;/h2&gt;

&lt;p&gt;In this post, we have seen a minimal Deno HTTP server working in a Nanos unikernel.&lt;/p&gt;

</description>
      <category>deno</category>
      <category>ops</category>
      <category>nanos</category>
      <category>typescript</category>
    </item>
    <item>
      <title>Hi, I'm Dario Castañé</title>
      <dc:creator>Dario Castañé</dc:creator>
      <pubDate>Thu, 22 Jun 2017 07:25:50 +0000</pubDate>
      <link>https://dev.to/dcc/hi-im-dario-casta</link>
      <guid>https://dev.to/dcc/hi-im-dario-casta</guid>
      <description>&lt;p&gt;I have been coding for too much years. I don't even remember. No, seriously, I was born in 1985 and I started to code in 1997.&lt;/p&gt;

&lt;p&gt;You can find me on GitHub as &lt;a href="https://github.com/imdario" rel="noopener noreferrer"&gt;imdario&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;I live in Barcelona (Catalonia).&lt;/p&gt;

&lt;p&gt;I work for &lt;a href="http://loyal.guru" rel="noopener noreferrer"&gt;Loyal Guru&lt;/a&gt; as tech lead.&lt;/p&gt;

&lt;p&gt;I mostly program in these languages: Ruby, Go, etc. I consider myself a polyglot programmer.&lt;/p&gt;

&lt;p&gt;I am currently learning more about blockchain, webcomponents, IoT, etc.&lt;/p&gt;

&lt;p&gt;Nice to meet you and happy hacking &amp;lt;3&lt;/p&gt;

</description>
      <category>introduction</category>
    </item>
  </channel>
</rss>
