wasmer.wasmer

Wasmer Python API

PyPI version Wasmer Python Documentation Wasmer PyPI downloads Wasmer Slack Channel

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

Features:

  • Easy to use: The wasmer API mimics the standard WebAssembly API,
  • Fast: wasmer executes the WebAssembly modules as fast as possible, close to native speed,
  • Safe: All calls to WebAssembly will be fast, but more importantly, completely safe and sandboxed.

Example

The very basic example is the following:

from wasmer import Store, Module, Instance

# Create a store, which holds the engine, the compiler etc.
store = Store()

# Let's assume we don't have WebAssembly bytes at hand. We will
# write WebAssembly manually.
module = Module(
    store,
    """
    (module
      (type (func (param i32 i32) (result i32)))
      (func (type 0)
        local.get 0
        local.get 1
        i32.add)
      (export "sum" (func 0)))
    """
)

# Instantiates the module.
instance = Instance(module)

# Now, let's execute the `sum` function.
assert instance.exports.sum(1, 2) == 3

That's it. Now explore the API! Some pointers for the adventurers:

  • The basic elements are Module and Instance,
  • Exports of an instance are represented by the Exports object,
  • Maybe your module needs to import Function, Memory, Global or Table? Well, there is the Python dict for that!
  • It is possible to read and write Memory data with the Python buffer protocol with Buffer.

Have fun!

#   __version__ = '1.1.0'
#   __core_version__ = '1.1.0'
#   def wat2wasm(wat):

Translate WebAssembly text source to WebAssembly binary format.

Example

from wasmer import wat2wasm

assert wat2wasm('(module)') == b'\x00asm\x01\x00\x00\x00'
#   def wasm2wat(bytes):

Disassemble WebAssembly binary to WebAssembly text format.

Example

from wasmer import wasm2wat

assert wasm2wat(b'\x00asm\x01\x00\x00\x00') == '(module)'
#   class Exports:

Represents all the exports of an instance. It is built by Instance.exports.

Exports can be of kind Function, Global, Table, or Memory.

The Exports class implement the Iterator Protocol. Please see the ExportsIterator class.

Example

from wasmer import Store, Module, Instance, Exports, Function, Global, Table, Memory

module = Module(
    Store(),
    """
    (module
      (func (export "func") (param i32 i64))
      (global (export "glob") i32 (i32.const 7))
      (table (export "tab") 0 funcref)
      (memory (export "mem") 1))
    """
)
instance = Instance(module)
exports = instance.exports

assert isinstance(exports, Exports)
assert isinstance(exports.func, Function)
assert isinstance(exports.glob, Global)
assert isinstance(exports.tab, Table)
assert isinstance(exports.mem, Memory)
#   Exports()
#   class ExportsIterator:

Iterator over all the exports of an Instance.

Example

from wasmer import Store, Module, Instance, Exports, Function, Global, Table, Memory

module = Module(
    Store(),
    """
    (module
      (func (export "func") (param i32 i64))
      (global (export "glob") i32 (i32.const 7))
      (table (export "tab") 0 funcref)
      (memory (export "mem") 1))
    """
)
instance = Instance(module)

assert [name for (name, export) in instance.exports] == ["func", "glob", "tab", "mem"]
#   ExportsIterator()
#   class Function:

Represents a WebAssembly function instance.

A function instance is the runtime representation of a function. It effectively is a closure of the original function (defined in either the host or the WebAssembly module) over the runtime Instance of its originating Module.

The module instance is used to resolve references to other definitions during executing of the function.

Specification: https://webassembly.github.io/spec/core/exec/runtime.html#function-instances

Note that the function can be invoked/called by the host only when it is an exported function (see Exports to see an example).

Example

To build a Function, we need its type. It can either be inferred from Python thanks to annotations, or be given with a FunctionType value.

With Python annotations

First, let's see with Python annotations:

from wasmer import Store, Function, Type

def sum(x: int, y: int) -> int:
    return x + y

store = Store()
function = Function(store, sum)
function_type = function.type

assert function_type.params == [Type.I32, Type.I32]
assert function_type.results == [Type.I32]

Here is the mapping table:

Annotations WebAssembly type
int, 'i32', 'I32' Type.I32
'i64', 'I64' Type.I64
float, 'f32', 'F32' Type.F32
'f64', 'F64' Type.F64
None none (only in return position)

It is possible for a host function to return a tuple of the types above (except None), like:

from wasmer import Store, Function, Type

def swap(x: 'i32', y: 'i64') -> ('i64', 'i32'):
    return (y, x)

store = Store()
function = Function(store, swap)
function_type = function.type

assert function_type.params == [Type.I32, Type.I64]
assert function_type.results == [Type.I64, Type.I32]

With FunctionType

Second, the same code but without annotations and a FunctionType:

from wasmer import Store, Function, FunctionType, Type

def sum(x, y):
    return x + y

store = Store()
function = Function(store, sum, FunctionType([Type.I32, Type.I32], [Type.I32]))
#   Function()
#   type

Returns the type of the function as a FunctionType object.

Example

from wasmer import Store, Module, Instance, FunctionType, Type

module = Module(
    Store(),
    """
    (module
      (type (func (param i32 i32) (result i32)))
      (func (type 0)
        local.get 0
        local.get 1
        i32.add)
      (export "sum" (func 0)))
    """
)
instance = Instance(module)
sum = instance.exports.sum
sum_type = sum.type

assert isinstance(sum_type, FunctionType)
assert sum_type.params == [Type.I32, Type.I32]
assert sum_type.results == [Type.I32]
#   class Global:

Represents a WebAssembly global instance.

A global instance is the runtime representation of a global variable. It consists of an individual value and a flag indicating whether it is mutable.

Specification: https://webassembly.github.io/spec/core/exec/runtime.html#global-instances

Example

from wasmer import Store, Global, Value, Type

store = Store()

# Let's create an immutable global.
global_ = Global(store, Value.i32(42))
global_type = global_.type

assert global_.value == 42
assert global_type.type == Type.I32
assert global_type.mutable == False

# Let's create an mutable global.
global_ = Global(store, Value.i32(42), mutable=True)

assert global_.mutable == True
#   Global()
#   type

Returns the type of the global as a value of kind GlobalType.

Example

from wasmer import Store, Global, Value, Type

store = Store()

global_ = Global(store, Value.i32(42), mutable=False)
global_type = global_.type

assert global_type.type == Type.I32
assert global_type.mutable == False
#   value

Get or set a custom value to the global instance.

Example

from wasmer import Store, Global, Value

store = Store()
global_ = Global(store, Value.i32(42), mutable=True)

assert global_.value == 42

global_.value = 153

assert global_.value == 153
#   mutable

Checks whether the global is mutable.

Example

from wasmer import Store, Global, Value

store = Store()
global_ = Global(store, Value.i32(42), mutable=True)

assert global_.mutable == True
#   class Memory:

A WebAssembly memory instance.

A memory instance is the runtime representation of a linear memory. It consists of a vector of bytes and an optional maximum size.

The length of the vector always is a multiple of the WebAssembly page size, which is defined to be the constant 65536 – abbreviated 64Ki. Like in a memory type, the maximum size in a memory instance is given in units of this page size.

A memory created by the host or in WebAssembly code will be accessible and mutable from both host and WebAssembly.

Specification: https://webassembly.github.io/spec/core/exec/runtime.html#memory-instances

Example

Creates a Memory from scratch:

from wasmer import Store, Memory, MemoryType

store = Store()
memory_type = MemoryType(minimum=3)
memory = Memory(store, memory_type)

assert memory.size == 3

Gets a memory from the exports of an instance:

from wasmer import Store, Module, Instance, Memory

module = Module(Store(), open('tests/tests.wasm', 'rb').read())
instance = Instance(module)

memory = instance.exports.memory

assert isinstance(memory, Memory)
#   Memory()
#   def grow(self, /, number_of_pages):

Grow memory by the specified amount of WebAssembly pages.

Example

from wasmer import Store, Memory, MemoryType

store = Store()
memory_type = MemoryType(minimum=3)
memory = Memory(store, memory_type)

assert memory.size == 3

memory.grow(2)

assert memory.size == 5
#   def uint8_view(self, /, offset=0):

Creates a read-and-write view over the memory data where elements are of kind uint8. See the Uint8Array view to learn more.

Examples

from wasmer import Store, Memory, MemoryType, Uint8Array

store = Store()
memory_type = MemoryType(minimum=3)
memory = Memory(store, memory_type)

assert isinstance(memory.uint8_view(offset=42), Uint8Array)
#   def int8_view(self, /, offset=0):

Creates a read-and-write over the memory data where elements are of kind int8. See the Int8Array view to learn more, and the Memory.uint8_view method to see an example.

#   def uint16_view(self, /, offset=0):

Creates a read-and-write over the memory data where elements are of kind uint16. See the Uint16Array view to learn more, and the Memory.uint8_view method to see an example.

#   def int16_view(self, /, offset=0):

Creates a read-and-write over the memory data where elements are of kind int16. See the Int16Array view to learn more, and the Memory.uint8_view method to see an example.

#   def uint32_view(self, /, offset=0):

Creates a read-and-write over the memory data where elements are of kind uint32. See the Uint32Array view to learn more, and the Memory.uint8_view method to see an example.

#   def int32_view(self, /, offset=0):

Creates a read-and-write over the memory data where elements are of kind int32. See the Int32Array view to learn more, and the Memory.uint8_view method to see an example.

#   def uint64_view(self, /, offset=0):

Creates a read-and-write over the memory data where elements are of kind uint64. See the Uint64Array view to learn more, and the Memory.uint8_view method to see an example.

#   def int64_view(self, /, offset=0):

Creates a read-and-write over the memory data where elements are of kind int64. See the Int64Array view to learn more, and the Memory.uint8_view method to see an example.

#   def float32_view(self, /, offset=0):

Creates a read-and-write over the memory data where elements are of kind float32. See the Float32Array view to learn more, and the Memory.uint8_view method to see an example.

#   def float64_view(self, /, offset=0):

Creates a read-and-write over the memory data where elements are of kind float64. See the Float64Array view to learn more, and the Memory.uint8_view method to see an example.

#   type

Gets the memory type, of kind MemoryType.

Example

from wasmer import Store, Memory, Module, Instance

module = Module(Store(), open('tests/tests.wasm', 'rb').read())
instance = Instance(module)
memory = instance.exports.memory
memory_type = memory.type

assert memory_type.minimum == 17
assert memory_type.maximum == None
assert memory_type.shared == False
#   data_size

Returns the size (in bytes) of the Memory.

Example

from wasmer import Store, Memory, MemoryType

store = Store()
memory_type = MemoryType(minimum=3)
memory = Memory(store, memory_type)

assert memory.data_size == 196608
#   size

Returns the size (in pages) of the Memory.

Example

from wasmer import Store, Memory, MemoryType

store = Store()
memory_type = MemoryType(minimum=3)
memory = Memory(store, memory_type)

assert memory.size == 3
#   buffer

Creates a Python buffer to read and write the memory data. See the Buffer class to learn more.

Example

from wasmer import Store, Memory, MemoryType, Buffer

store = Store()
memory_type = MemoryType(minimum=3)
memory = Memory(store, memory_type)

assert isinstance(memory.buffer, Buffer)
#   class Table:

A WebAssembly table instance.

The Table class is an array-like structure representing a WebAssembly table, which stores function references.

A table created by the host or in WebAssembly code will be accessible and mutable from both host and WebAssembly.

Specification: https://webassembly.github.io/spec/core/exec/runtime.html#table-instances

#   Table()
#   type

Gets the table type, as an object of kind TableType.

Example

from wasmer import Store, Module, Instance, Table, Type

module = Module(Store(), '(module (table (export "table") 2 funcref))')
instance = Instance(module)
table = instance.exports.table
table_type = table.type

assert table_type.type == Type.FUNC_REF
assert table_type.minimum == 2
assert table_type.maximum == None
#   size

Gets the table size (in elements).

Example

from wasmer import Store, Module, Instance, Table

module = Module(Store(), '(module (table (export "table") 2 funcref))')
instance = Instance(module)
table = instance.exports.table

assert table.size == 2
#   class ImportObject:

An ImportObject represents all of the import data used when instantiating a WebAssembly module.

Important

This object is deprecated in favor of dictionaries in Python. You can now type:

from wasmer import Store, Function

def sum(x: int, y: int) -> int:
    return x + y

store = Store()
import_object = {}
import_object["math"] = {
    "sum": Function(store, sum)
}

Example

Importing a function, math.sum, and call it through the exported add_one function:

from wasmer import Store, Module, Instance, ImportObject, Function
def sum(x: int, y: int) -> int:
    return x + y

store = Store()
module = Module(
    store,
    """
    (module
      (import "math" "sum" (func $sum (param i32 i32) (result i32)))
      (func (export "add_one") (param i32) (result i32)
        local.get 0
        i32.const 1
        call $sum))
    """
)

import_object = ImportObject()
import_object.register(
    "math",
    {
        "sum": Function(store, sum)
    }
)

instance = Instance(module, import_object)

assert instance.exports.add_one(1) == 2

Importing a memory:

from wasmer import Store, Module, Instance, Memory, MemoryType, ImportObject

store = Store()
module = Module(
    store,
    """
    (module
      (import "env" "memory" (memory $memory 1))
      (func (export "increment")
        i32.const 0
        i32.const 0
        i32.load    ;; load 0
        i32.const 1
        i32.add     ;; add 1
        i32.store   ;; store at 0
        ))
    """
)

memory = Memory(store, MemoryType(minimum=1))
view = memory.uint8_view(offset=0)

import_object = ImportObject()
import_object.register(
    "env",
    {
        "memory": memory
    }
)

instance = Instance(module, import_object)

assert view[0] == 0
instance.exports.increment()
assert view[0] == 1
instance.exports.increment()
assert view[0] == 2

Importing a global:

from wasmer import Store, Module, Instance, ImportObject, Global, Value

store = Store()
module = Module(
    store,
    """
    (module
      (import "env" "global" (global $global (mut i32)))
      (func (export "read_g") (result i32)
        global.get $global)
      (func (export "write_g") (param i32)
        local.get 0
        global.set $global))
    """
)

global_ = Global(store, Value.i32(7), mutable=True)

import_object = ImportObject()
import_object.register(
    "env",
    {
        "global": global_
    }
)

instance = Instance(module, import_object)

assert instance.exports.read_g() == 7
global_.value = 153
assert instance.exports.read_g() == 153
instance.exports.write_g(11)
assert global_.value == 11

etc.

#   ImportObject()
#   def contains_namespace(self, /, namespace_name):

Checks whether the import object contains a specific namespace.

Example

from wasmer import ImportObject

import_object = ImportObject()

assert import_object.contains_namespace("foo") == False
#   def to_dict(self, /):

Gets a Python dictionary from an ImportObject.

#   def register(self, /, namespace_name, namespace):

Registers a set of Function, Memory, Global or Table to a particular namespace.

Example

from wasmer import Store, ImportObject, Function, Memory, MemoryType

store = Store()

def sum(x: int, y: int) -> int:
    return x + y

import_object = ImportObject()
import_object.register(
    "env",
    {
        "sum": Function(store, sum),
        "memory": Memory(store, MemoryType(minimum=1))
    }
)
#   class Instance:

A WebAssembly instance is a stateful, executable instance of a WebAssembly Module.

Instance objects contain all the exported WebAssembly functions, memories, tables and globals that allow interacting with WebAssembly.

Specification: https://webassembly.github.io/spec/core/exec/runtime.html#module-instances

Example

Example without an import object. The following creates a module with a sum exported function that sum two integers.

from wasmer import Store, Module, Instance

module = Module(
    Store(),
    """
    (module
      (type (func (param i32 i32) (result i32)))
      (func (type 0)
        local.get 0
        local.get 1
        i32.add)
      (export "sum" (func 0)))
    """
)
instance = Instance(module)

assert instance.exports.sum(1, 2) == 3

Example with an import object. The following creates a module that (i) imports a sum function from the math namespace, and (ii) exports a add_one function that adds 1 to any given integer (by using the math.sum function).

from wasmer import Store, Module, Instance, Function
from collections import defaultdict

# Let's define the `sum` function!
def sum(x: int, y: int) -> int:
    return x + y

# Let's build a store, as usual.
store = Store()

# Let's compile the WebAssembly module.
module = Module(
    store,
    """
    (module
      (import "math" "sum" (func $sum (param i32 i32) (result i32)))
      (func (export "add_one") (param i32) (result i32)
        local.get 0
        i32.const 1
        call $sum))
    """
)

# Now, let's create an import object, and register the `sum`
# function.
import_object = defaultdict(dict)
import_object["math"]["sum"] = Function(store, sum)

# Here we go, let's instantiate the module with the import object!
instance = Instance(module, import_object)

# Let's test it!
assert instance.exports.add_one(41) == 42
#   Instance()
#   exports

The exports of the instance, as an object of kind Exports.

Example

See the Exports class.

#   class Buffer:

Represents a read-and-write buffer over data of a memory.

It is built by the Memory.buffer getter.

It implements the Python buffer protocol, so it is possible to read and write bytes with bytes, bytearray or memoryview.

Example

from wasmer import Memory, MemoryType, Store

store = Store()
memory = Memory(store, MemoryType(minimum=128))

# Let's write data with a `Int8Array` view for example.
int8 = memory.int8_view()
int8[0] = 1
int8[1] = 2
int8[2] = 3
int8[3] = 0x57
int8[4] = 0x61
int8[5] = 0x73
int8[6] = 0x6d
int8[7] = 0x65
int8[8] = 0x72

# Let's read data with a `Buffer` for example.
byte_array = bytearray(memory.buffer)

assert byte_array[0:3] == b'\x01\x02\x03'
assert byte_array[3:9].decode() == 'Wasmer'
#   Buffer()
#   class Float32Array:

Represents a read-and-write view over the data of a memory.

It is built by the Memory.uint8_view and siblings getters.

It implements the Python mapping protocol, so it is possible to read and write bytes with a standard Python API.

Example

This is an example for the Uint8Array view, but it is the same for its siblings!

from wasmer import Store, Module, Instance, Uint8Array

module = Module(Store(), open('tests/tests.wasm', 'rb').read())
instance = Instance(module)
exports = instance.exports

pointer = exports.string()
memory = exports.memory.uint8_view(offset=pointer)
nth = 0
string = ''

while (0 != memory[nth]):
    string += chr(memory[nth])
    nth += 1

assert string == 'Hello, World!'
#   Float32Array()
#   bytes_per_element

Gets the number of bytes per element.

#   class Float64Array:

Represents a read-and-write view over the data of a memory.

It is built by the Memory.uint8_view and siblings getters.

It implements the Python mapping protocol, so it is possible to read and write bytes with a standard Python API.

Example

This is an example for the Uint8Array view, but it is the same for its siblings!

from wasmer import Store, Module, Instance, Uint8Array

module = Module(Store(), open('tests/tests.wasm', 'rb').read())
instance = Instance(module)
exports = instance.exports

pointer = exports.string()
memory = exports.memory.uint8_view(offset=pointer)
nth = 0
string = ''

while (0 != memory[nth]):
    string += chr(memory[nth])
    nth += 1

assert string == 'Hello, World!'
#   Float64Array()
#   bytes_per_element

Gets the number of bytes per element.

#   class Int16Array:

Represents a read-and-write view over the data of a memory.

It is built by the Memory.uint8_view and siblings getters.

It implements the Python mapping protocol, so it is possible to read and write bytes with a standard Python API.

Example

This is an example for the Uint8Array view, but it is the same for its siblings!

from wasmer import Store, Module, Instance, Uint8Array

module = Module(Store(), open('tests/tests.wasm', 'rb').read())
instance = Instance(module)
exports = instance.exports

pointer = exports.string()
memory = exports.memory.uint8_view(offset=pointer)
nth = 0
string = ''

while (0 != memory[nth]):
    string += chr(memory[nth])
    nth += 1

assert string == 'Hello, World!'
#   Int16Array()
#   bytes_per_element

Gets the number of bytes per element.

#   class Int32Array:

Represents a read-and-write view over the data of a memory.

It is built by the Memory.uint8_view and siblings getters.

It implements the Python mapping protocol, so it is possible to read and write bytes with a standard Python API.

Example

This is an example for the Uint8Array view, but it is the same for its siblings!

from wasmer import Store, Module, Instance, Uint8Array

module = Module(Store(), open('tests/tests.wasm', 'rb').read())
instance = Instance(module)
exports = instance.exports

pointer = exports.string()
memory = exports.memory.uint8_view(offset=pointer)
nth = 0
string = ''

while (0 != memory[nth]):
    string += chr(memory[nth])
    nth += 1

assert string == 'Hello, World!'
#   Int32Array()
#   bytes_per_element

Gets the number of bytes per element.

#   class Int64Array:

Represents a read-and-write view over the data of a memory.

It is built by the Memory.uint8_view and siblings getters.

It implements the Python mapping protocol, so it is possible to read and write bytes with a standard Python API.

Example

This is an example for the Uint8Array view, but it is the same for its siblings!

from wasmer import Store, Module, Instance, Uint8Array

module = Module(Store(), open('tests/tests.wasm', 'rb').read())
instance = Instance(module)
exports = instance.exports

pointer = exports.string()
memory = exports.memory.uint8_view(offset=pointer)
nth = 0
string = ''

while (0 != memory[nth]):
    string += chr(memory[nth])
    nth += 1

assert string == 'Hello, World!'
#   Int64Array()
#   bytes_per_element

Gets the number of bytes per element.

#   class Int8Array:

Represents a read-and-write view over the data of a memory.

It is built by the Memory.uint8_view and siblings getters.

It implements the Python mapping protocol, so it is possible to read and write bytes with a standard Python API.

Example

This is an example for the Uint8Array view, but it is the same for its siblings!

from wasmer import Store, Module, Instance, Uint8Array

module = Module(Store(), open('tests/tests.wasm', 'rb').read())
instance = Instance(module)
exports = instance.exports

pointer = exports.string()
memory = exports.memory.uint8_view(offset=pointer)
nth = 0
string = ''

while (0 != memory[nth]):
    string += chr(memory[nth])
    nth += 1

assert string == 'Hello, World!'
#   Int8Array()
#   bytes_per_element

Gets the number of bytes per element.

#   class Uint16Array:

Represents a read-and-write view over the data of a memory.

It is built by the Memory.uint8_view and siblings getters.

It implements the Python mapping protocol, so it is possible to read and write bytes with a standard Python API.

Example

This is an example for the Uint8Array view, but it is the same for its siblings!

from wasmer import Store, Module, Instance, Uint8Array

module = Module(Store(), open('tests/tests.wasm', 'rb').read())
instance = Instance(module)
exports = instance.exports

pointer = exports.string()
memory = exports.memory.uint8_view(offset=pointer)
nth = 0
string = ''

while (0 != memory[nth]):
    string += chr(memory[nth])
    nth += 1

assert string == 'Hello, World!'
#   Uint16Array()
#   bytes_per_element

Gets the number of bytes per element.

#   class Uint32Array:

Represents a read-and-write view over the data of a memory.

It is built by the Memory.uint8_view and siblings getters.

It implements the Python mapping protocol, so it is possible to read and write bytes with a standard Python API.

Example

This is an example for the Uint8Array view, but it is the same for its siblings!

from wasmer import Store, Module, Instance, Uint8Array

module = Module(Store(), open('tests/tests.wasm', 'rb').read())
instance = Instance(module)
exports = instance.exports

pointer = exports.string()
memory = exports.memory.uint8_view(offset=pointer)
nth = 0
string = ''

while (0 != memory[nth]):
    string += chr(memory[nth])
    nth += 1

assert string == 'Hello, World!'
#   Uint32Array()
#   bytes_per_element

Gets the number of bytes per element.

#   class Uint64Array:

Represents a read-and-write view over the data of a memory.

It is built by the Memory.uint8_view and siblings getters.

It implements the Python mapping protocol, so it is possible to read and write bytes with a standard Python API.

Example

This is an example for the Uint8Array view, but it is the same for its siblings!

from wasmer import Store, Module, Instance, Uint8Array

module = Module(Store(), open('tests/tests.wasm', 'rb').read())
instance = Instance(module)
exports = instance.exports

pointer = exports.string()
memory = exports.memory.uint8_view(offset=pointer)
nth = 0
string = ''

while (0 != memory[nth]):
    string += chr(memory[nth])
    nth += 1

assert string == 'Hello, World!'
#   Uint64Array()
#   bytes_per_element

Gets the number of bytes per element.

#   class Uint8Array:

Represents a read-and-write view over the data of a memory.

It is built by the Memory.uint8_view and siblings getters.

It implements the Python mapping protocol, so it is possible to read and write bytes with a standard Python API.

Example

This is an example for the Uint8Array view, but it is the same for its siblings!

from wasmer import Store, Module, Instance, Uint8Array

module = Module(Store(), open('tests/tests.wasm', 'rb').read())
instance = Instance(module)
exports = instance.exports

pointer = exports.string()
memory = exports.memory.uint8_view(offset=pointer)
nth = 0
string = ''

while (0 != memory[nth]):
    string += chr(memory[nth])
    nth += 1

assert string == 'Hello, World!'
#   Uint8Array()
#   bytes_per_element

Gets the number of bytes per element.

#   class Module:

A WebAssembly module contains stateless WebAssembly code that has already been compiled and can be instantiated multiple times.

Creates a new WebAssembly Module given the configuration in the store.

If the provided bytes are not WebAssembly-like (start with b"\0asm"), this function will try to to convert the bytes assuming they correspond to the WebAssembly text format.

Security

Before the code is compiled, it will be validated using the store features.

Example

from wasmer import Store, Module

store = Store()

# Let's compile WebAssembly from bytes.
module = Module(store, open('tests/tests.wasm', 'rb').read())

# Let's compile WebAssembly from WAT.
module = Module(store, '(module)')
#   Module()
#   def validate(bytes):

Validates a new WebAssembly Module given the configuration in the Store.

This validation is normally pretty fast and checks the enabled WebAssembly features in the Store engine to assure deterministic validation of the Module.

Example

from wasmer import Store, Module

assert Module.validate(Store(), wasm_bytes)
#   def custom_sections(self, /, name):

Get the custom sections of the module given a name.

Important

Following the WebAssembly specification, one name can have multiple custom sections. That's why a list of bytes is returned rather than bytes.

Consequently, the empty list represents the absence of a custom section for the given name.

Examples

from wasmer import Store, Module

module = Module(Store(), open('tests/custom_sections.wasm', 'rb').read())

assert module.custom_sections('easter_egg') == [b'Wasmer']
assert module.custom_sections('hello') == [b'World!']
assert module.custom_sections('foo') == []
#   def serialize(self, /):

Serializes a module into a binary representation that the Engine can later process via Module.deserialize.

Examples

from wasmer import Store, Module

store = Store()
module = Module(Store(), '(module)')
serialized_module = module.serialize()

assert type(serialized_module) == bytes
#   def deserialize(self, /, bytes):

Deserializes a serialized module binary into a Module.

Note: the module has to be serialized before with the serialize method.

Safety

This function is inherently unsafe as the provided bytes:

  1. Are going to be deserialized directly into Rust objects.
  2. Contains the function assembly bodies and, if intercepted, a malicious actor could inject code into executable memory.

And as such, the deserialize method is unsafe.

Example

from wasmer import Store, Module

store = Store()
module = Module(
    store,
    """
    (module
      (func (export "function") (param i32 i64)))
    """
)
serialized_module = module.serialize()

del module

module = Module.deserialize(store, serialized_module)

del serialized_module

assert isinstance(module, Module)
#   exports

Returns a list of ExportType objects, which represents all the exports of this module.

The order of the exports is guaranteed to be the same as in the WebAssembly bytecode.

Example

See the ExportType class to learn more.

#   imports

Returns a list of ImportType objects, which represents all the imports of this module.

The order of the imports is guaranteed to be the same as in the WebAssembly bytecode.

Example

See the ImportType class to learn more.

#   name

Get or set the current name of the module.

This name is normally set in the WebAssembly bytecode by some compilers, but can be also overwritten.

Not all modules have a name.

Example

from wasmer import Store, Module

store = Store()

# Module with an existing name.
assert Module(store, '(module $moduleName)').name == 'moduleName'

# Module with no name.
assert Module(store, '(module)').name == None

# Change the module's name.
module = Module(store, '(module $moduleName)')
module.name = 'hello'
assert module.name == 'hello'
#   class Store:

The store represents all global state that can be manipulated by WebAssembly programs. It consists of the runtime representation of all instances of functions, tables, memories, and globals that have been allocated during the lifetime of the abstract machine.

The Store holds the engine (that is —amongst many things— used to compile the WebAssembly bytes into a valid module artifact), in addition to the Tunables (that are used to create the memories, tables and globals). The engine comes from the wasmer.engine module.

Specification: https://webassembly.github.io/spec/core/exec/runtime.html#store

Read the documentation of the engine submodule to learn more.

Examples

Use the Universal engine with no compiler (headless mode):

from wasmer import engine, Store

store = Store(engine.Universal())

Use the Universal engine with the LLVM compiler:

from wasmer import engine, Store
from wasmer_compiler_llvm import Compiler

store = Store(engine.Universal(Compiler))

If the store is built without an engine, the Universal engine will be used, with the first compiler found in this order: compiler_compiler_cranelift, compiler_compiler_llvm, compiler_compiler_singlepass, otherwise it will run in headless mode.

#   Store()
#   compiler_name
#   engine_name
#   class ExportType:

Represents the type of a module's export (not to be confused with an export of an instance). It is usually built from the Module.exports getter.

Examples

from wasmer import Store, Module, ExportType, FunctionType, GlobalType, TableType, MemoryType, Type

module = Module(
    Store(),
    """
    (module
      (func (export "function") (param i32 i64))
      (global (export "global") i32 (i32.const 7))
      (table (export "table") 0 funcref)
      (memory (export "memory") 1))
    """
)

exports = module.exports

assert isinstance(exports[0], ExportType)

assert exports[0].name == "function"
assert isinstance(exports[0].type, FunctionType)
assert exports[0].type.params == [Type.I32, Type.I64]
assert exports[0].type.results == []

assert exports[1].name == "global"
assert isinstance(exports[1].type, GlobalType)
assert exports[1].type.type == Type.I32
assert exports[1].type.mutable == False

assert exports[2].name == "table"
assert isinstance(exports[2].type, TableType)
assert exports[2].type.type == Type.FUNC_REF
assert exports[2].type.minimum == 0
assert exports[2].type.maximum == None

assert exports[3].name == "memory"
assert isinstance(exports[3].type, MemoryType)
assert exports[3].type.minimum == 1
assert exports[3].type.maximum == None
assert exports[3].type.shared == False
#   ExportType()
#   type

The type of the export. Possible values are: FunctionType, GlobalType, TableType and MemoryType.

#   name

The name of the export.

#   class FunctionType:

Represents the signature of a function that is either implemented in WebAssembly module or exposed to WebAssembly by the host.

WebAssembly functions can have 0 or more parameters and results.

Example

from wasmer import FunctionType, Type

# Type: (i32, i32) -> i32
function_type = FunctionType(
    params=[Type.I32, Type.I32],
    results=[Type.I32]
)
#   FunctionType()
#   params

Parameters, i.e. inputs, of the function.

#   results

Results, i.e. outputs, of the function.

#   class GlobalType:

A descriptor for a WebAssembly global.

Example

from wasmer import GlobalType, Type

# Describes a global of kind `i32` which is immutable.
global_type = GlobalType(Type.I32, mutable=False)
#   GlobalType()
#   type

The type of the value stored in the global.

#   mutable

A flag indicating whether the value may change at runtime.

#   class ImportType:

Represents the type of a module's import. It is usually built from the Module.imports getter.

Example

from wasmer import Store, Module, ImportType, FunctionType, GlobalType, TableType, MemoryType, Type

module = Module(
    Store(),
    """
    (module
    (import "ns" "function" (func))
    (import "ns" "global" (global f32))
    (import "ns" "table" (table 1 2 anyfunc))
    (import "ns" "memory" (memory 3 4)))
    """
)
imports = module.imports

assert isinstance(imports[0], ImportType)

assert imports[0].module == "ns"
assert imports[0].name == "function"
assert isinstance(imports[0].type, FunctionType)
assert imports[0].type.params == []
assert imports[0].type.results == []

assert imports[1].module == "ns"
assert imports[1].name == "global"
assert isinstance(imports[1].type, GlobalType)
assert imports[1].type.type == Type.F32
assert imports[1].type.mutable == False

assert imports[2].module == "ns"
assert imports[2].name == "table"
assert isinstance(imports[2].type, TableType)
assert imports[2].type.type == Type.FUNC_REF
assert imports[2].type.minimum == 1
assert imports[2].type.maximum == 2

assert imports[3].module == "ns"
assert imports[3].name == "memory"
assert isinstance(imports[3].type, MemoryType)
assert imports[3].type.minimum == 3
assert imports[3].type.maximum == 4
assert imports[3].type.shared == False
#   ImportType()
#   type

The type of the import. Possible values are: FunctionType, GlobalType, TableType and MemoryType.

#   module

The namespace name (also known as module name).

#   name

The name of the import.

#   class MemoryType:

A descriptor for a WebAssembly memory type.

Memories are described in units of pages (64Kb) and represent contiguous chunks of addressable memory.

Example

from wasmer import MemoryType

memory_type = MemoryType(
    minimum=1,
    shared=True
)
#   MemoryType()
#   maximum

The maximum number of pages in the memory. It is optional.

#   minimum

The minimum number of pages in the memory.

#   shared

Whether the memory may be shared between multiple threads.

#   class TableType:

A descriptor for a table in a WebAssembly module.

Tables are contiguous chunks of a specific element, typically a funcref or externref. The most common use for tables is a function table through which call_indirect can invoke other functions.

Example

from wasmer import TableType, Type

table_type = TableType(Type.I32, minimum=7, maximum=42)
#   TableType()
#   minimum

The minimum number of elements in the table.

#   type

The type of data stored in elements of the table.

#   maximum

The maximum number of elements in the table.

#   class Value:

Represents a WebAssembly value of a specific type.

Most of the time, the types for WebAssembly values will be inferred. When it's not possible, the Value class is necessary.

Example

from wasmer import Value

value = Value.i32(42)
#   Value()
#   def i32(value):

Build a WebAssembly i32 value.

Example

from wasmer import Value

value = Value.i32(42)
#   def i64(value):

Build a WebAssembly i64 value.

Example

from wasmer import Value

value = Value.i64(42)
#   def f32(value):

Build a WebAssembly f32 value.

Example

from wasmer import Value

value = Value.f32(4.2)
#   def f64(value):

Build a WebAssembly f64 value.

Example

from wasmer import Value

value = Value.f64(4.2)
#   def v128(value):

Build a WebAssembly v128 value.

Example

from wasmer import Value

value = Value.v128(42)
#   class Type(enum.IntEnum):

An enumeration.

#   I32 = <Type.I32: 1>
#   I64 = <Type.I64: 2>
#   F32 = <Type.F32: 3>
#   F64 = <Type.F64: 4>
#   V128 = <Type.V128: 5>
#   EXTERN_REF = <Type.EXTERN_REF: 6>
#   FUNC_REF = <Type.FUNC_REF: 7>
Inherited Members
enum.Enum
name
value
builtins.int
conjugate
bit_length
bit_count
to_bytes
from_bytes
as_integer_ratio
real
imag
numerator
denominator
#   engine

Wasmer Engines.

Engines are mainly responsible for two things:

  1. Transform the compilation code (from any Wasmer compiler) to create an artifact,
  2. Load an atifact so it can be used by the user (normally, pushing the code into executable memory and so on).

It currently has two implementations:

  1. Universal with engine.Universal,
  2. Dylib with engine.Dylib.

Both engines receive an optional compiler. If absent, engines will run in headless mode, i.e. they won't be able to compile (create) an artifact), they will only be able to run (load) an artifact.

Compilers are distributed as individual Python packages:

Example

Create a Universal engine with no compiler (headless mode):

from wasmer import engine

engine = engine.Universal()

Create a Universal engine with the LLVM compiler:

from wasmer import engine
from wasmer_compiler_llvm import Compiler

engine = engine.Universal(Compiler)

Engines are stored inside the wasmer.Store.

#   target

Wasmer's compilation targets.

Wasmer has several compilers used by the engines (wasmer.engine) when a WebAssembly module needs to be compiled. The Wasmer's architecture allows to compile for any targets. It allows to cross-compile a WebAssembly module, i.e. to compile from another architecture than the host's.

This module provides the Target class that allows to define a target for the compiler. A Target is defined by a Triple and CpuFeatures (optional).

Example

from wasmer import engine, target, Store, Module
from wasmer_compiler_cranelift import Compiler

# Build a triple from a string.
triple = target.Triple('x86_64-linux-musl')

# Build the CPU features (optional).
cpu_features = target.CpuFeatures()
cpu_features.add('sse2')

# Build the target.
target = target.Target(triple, cpu_features)

# There we go. When creating the engine, pass the compiler _and_
# the target.
engine = engine.Dylib(Compiler, target)

# And finally, build the store with the engine.
store = Store(engine)

# Now, let's compile the module for the defined target.
module = Module(
    store,
    """
    (module
    (type $sum_t (func (param i32 i32) (result i32)))
    (func $sum_f (type $sum_t) (param $x i32) (param $y i32) (result i32)
        local.get $x
        local.get $y
        i32.add)
    (export "sum" (func $sum_f)))
    """
)

# What's next? Serialize the module, and execute it on the
# targeted host.
#   wasi

Wasmer's WASI implementation.

From the user perspective, WASI is a bunch of imports. To generate the appropriated imports, you can use StateBuilder to build an Environment. This environment holds the WASI memory, and can be used to generate a valid wasmer.ImportObject. This last one can be passed to wasmer.Instance to instantiate a wasmer.Module that needs WASI support.

Example

from wasmer import wasi, Store, Module, Instance

store = Store()
module = Module(store, open('tests/wasi.wasm', 'rb').read())

# Get the WASI version.
wasi_version = wasi.get_version(module, strict=True)

# Build a WASI environment for the imports.
wasi_env = wasi.StateBuilder('test-program').argument('--foo').finalize()

# Generate an `ImportObject` from the WASI environment.
import_object = wasi_env.generate_import_object(store, wasi_version)

# Now we are ready to instantiate the module.
instance = Instance(module, import_object)

# Here we go, let's start the program.
instance.exports._start()