Wasmer logo

Wasmer Crystal

Build Status License API Documentation

Wasmer Website Shard Docs Wasmer Slack Channel


A complete and mature WebAssembly runtime for Crystal based on Wasmer.

Features

Documentation: browse the detailed API documentation

Examples as tutorials: browser the examples/ directory, it's the best place for a complete introduction!


NOTE: Shard assumes you have wasmer runtime version 2.XX installed and environment variable WASMER_DIR is setup properly, or you will encounter issues during compilation.


Quick Introduction

The wasmer package brings the required API to execute WebAssembly modules. In a nutshell, wasmer compiles the WebAssembly module into compiled code, and then executes it. wasmer is designed to work in various environments and platforms. To achieve this, Wasmer (the original runtime) provides multiple engines and multiple compilers.

Succinctly, an engine is responsible to drive the compilation (by using a compiler) and the execution of a WebAssembly module. Wasmer comes with many engines and compilers.

Installation

  1. Add the dependency to your shard.yml:

    dependencies
      wasmer:
        github: naqvis/wasmer-crystal
  2. Run shards install

And you're ready to get fun!

Usage

require "wasmer"

Example

We highly recommend to read the examples/ directory, which contains a sequence of examples/tutorials. It's the best place to learn by reading examples.

But for the most eager of you, and we know you're numerous you mischievous, there is a quick toy program in examples/appendices/simple.rs, written in Rust:

#[no_mangle]
pub extern fn sum(x: i32, y: i32) -> i32 {
    x + y
}

After compilation to WebAssembly, the examples/appendices/simple.wasm binary file is generated.

Then, we can execute it in Crystal:

require "wasmer"

# Let's define the engine, that holds the compiler.
engine = Wasmer::Engine.new 

# Let's define the store, that holds the engine, that holds the compiler.
store = Wasmer::Store.new(engine)

# Above two lines are same as invoking below helper method
# store = Wasmer.default_engine.new_store

# Let's compile the module to be able to execute it!
module_ = Wasmer::Module.new store, File.read("#{__DIR__}/simple.wasm")

# Now the module is compiled, we can instantiate it.
instance = Wasmer::Instance.new module_

# get the exported `sum` function
# function methods returns nil if it can't find the requested function. we know its there, so let's add `not_nil!` 
sum = instance.function("sum").not_nil!

# Call the exported `sum` function with Crystal standard values. The WebAssembly
# types are inferred and values are casted automatically.
result = sum.call(5, 37)

puts result # => 42

And then, finally, enjoy by running:

$ crystal examples/appendices/simple.cr

Development

To run all tests

crystal spec

What is WebAssembly?

Quoting the WebAssembly site:

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 applications.

About speed:

WebAssembly aims to execute at native speed by taking advantage of common hardware capabilities available on a wide range of platforms.

About safety:

WebAssembly describes a memory-safe, sandboxed execution environment […].

License

The entire project is under the MIT License. Please read the LICENSE file.

Contributing

  1. Fork it (https://github.com/naqvis/wasmer-crystal/fork)
  2. Create your feature branch (git checkout -b my-new-feature)
  3. Commit your changes (git commit -am 'Add some feature')
  4. Push to the branch (git push origin my-new-feature)
  5. Create a new Pull Request

Contributors