API

The extism python SDK, used for embedding guest Wasm programs into python hosts.

class extism.Plugin(plugin, wasi=False, config=None, functions=[])

Plugins are used to call WASM functions. Plugins can kept in a context for as long as you need. They may be freed with the del keyword.

import extism

with extism.Plugin({
    # all three of these wasm modules will be instantiated and their exported functions
    # made available to the `plugin` variable below.
    wasm: [
        { 'url': 'https://example.com/path/to/module.wasm' }
        { 'data': b'\xde\xad\xbe\xef' } # byte content representing a wasm module
        { 'url': 'https://example.com/path/to/module.wasm', hash: 'cafebeef' } # check that the downloaded module matches a specified sha256 hash.
    ],
}) as plugin:
    plugin.call("example-function")
Parameters:
  • plugin (Union[str, bytes, dict]) –

    Plugin data, passed as bytes representing a single WebAssembly module, a string representing a serialized JSON Manifest, or a dict respresenting a deserialized Manifest.

  • wasi (bool) – Indicates whether WASI preview 1 support will be enabled for this plugin.

  • config (Optional[Any]) – An optional JSON-serializable object holding a map of configuration keys and values.

  • functions (Optional[List[Function]]) – An optional list of host functions to expose to the guest program. Defaults to all registered @host_fn()’s if not given.

function_exists(name)

Given a function name, check whether the name is exported from this function.

Parameters:

name (str) – The function name to query.

Return type:

bool

call(function_name, data, parse=<function Plugin.<lambda>>)

Call a function by name with the provided input data

Parameters:
  • function_name (str) – The name of the function to invoke

  • data (Union[str, bytes]) – The input data to the function.

  • parse (Callable[[Any], Any]) – The function used to parse the buffer returned by the guest function call. Defaults to bytes.

Raises:

An extism.Error if the guest function call was unsuccessful.

Return type:

Any

Returns:

The returned bytes from the guest function as interpreted by the parse parameter.

exception extism.Error

A subclass of Exception representing a failed guest function call. Contains one argument: the error output.

class extism.CurrentPlugin(p)

This object is accessible when calling from the guest Plugin into the host via a host Function. It provides plugin memory access to host functions.

memory(mem)

Given a reference to plugin memory, return an FFI buffer

Parameters:

mem (Memory) – A memory reference to be accessed

Return type:

buffer

alloc(size)

Allocate a new block of memory.

Parameters:

size (int) – The number of bytes to allocate. Must be a positive integer.

Return type:

Memory

free(mem)

Free a block of memory by Memory reference

memory_at_offset(offs)

Given a memory offset, return the corresponding a Memory reference.

Return type:

Memory

return_bytes(output, b)

A shortcut for returning bytes from a host function.

Parameters:
  • output (Val) – This argument will be mutated and made to hold the memory address of b.

  • b (bytes) – The bytes to return.

return_string(output, s)

A shortcut for returning str from a host function.

Parameters:
  • output (Val) – This argument will be mutated and made to hold the memory address of s.

  • s (str) – The string to return.

input_bytes(input)

A shortcut for accessing bytes passed at the input parameter.

Parameters:

input (Val) – The input value that references bytes.

Return type:

bytes

input_string(input)

A shortcut for accessing str passed at the input parameter.

@extism.host_fn(signature=([extism.ValType.I64], []))
def hello_world(plugin, params, results):
    my_str = plugin.input_string(params[0])
    print(my_str)

# assume the following wasm file exists:
# example.wat = """
# (module
#     (import "example" "hello_world" (func $hello (param i64)))
#     (import "env" "extism_alloc" (func $extism_alloc (param i64) (result i64)))
#     (import "env" "extism_store_u8" (func $extism_store_u8 (;6;) (param i64 i32)))
#
#     (memory $memory (export "mem")
#       (data "Hello from WAT!")
#     )
#     (func $my_func (result i64)
#
#       ;; allocate extism memory and copy our message into it
#       (local $offset i64) (local $i i32)
#       (local.set $offset (call $extism_alloc (i64.const 15)))
#       (block $end
#         (loop $loop
#           (br_if $end (i32.eq (i32.const 0) (i32.load8_u (local.get $i))))
#           (call $extism_store_u8 (i64.add (local.get $offset) (i64.extend_i32_u (local.get $i))) (i32.load8_u (local.get $i)))
#           (local.set $i (i32.add (i32.const 1) (local.get $i)))
#           br $loop
#         )
#       )
#
#       ;; call our hello_world function with our extism memory offset.
#       local.get $offset
#       call $hello
#       i64.const 0
#     )
#     (export "my_func" (func $my_func))
# )
# """
# ... and we've compiled it using "wasm-tools parse example.wat -o example.wasm"
with open("example.wasm", "rb") as wasm_file:
    data = wasm_file.read()

with extism.Plugin(data, functions=[hello_world]) as plugin:
    plugin.call("my_func", "")
Parameters:

input (Val) – The input value that references a string.

Return type:

str

extism.set_log_file(file, level=None)

Sets the log file and level, this is a global configuration

Parameters:
  • file (str) – The path to the logfile

  • level (Optional[Literal['debug', 'error', 'trace', 'warn']]) – The debug level.

extism.extism_version()

Gets the Extism version string

Return type:

str

Returns:

The Extism runtime version string

class extism.Memory(offs, length)

A reference to plugin memory.

extism.host_fn(name=None, namespace=None, signature=None, user_data=None)

A decorator for creating host functions. Host functions are installed into a thread-local registry.

Parameters:
  • name (Optional[str]) – The function name to expose to the guest plugin. If not given, inferred from the wrapped function name.

  • namespace (Optional[str]) – The namespace to install the function into; defaults to “env” if not given.

  • signature (Optional[Tuple[List[ValType], List[ValType]]]) – A tuple of two arrays representing the function parameter types and return value types. If not given, types will be inferred from typing annotations.

  • userdata – Any custom userdata to associate with the function.

Supported Inferred Types

  • typing.Annotated[Any, extism.Json]: In both parameter and return positions. Written to extism memory; offset encoded in return value as I64.

  • typing.Annotated[Any, extism.Pickle]: In both parameter and return positions. Written to extism memory; offset encoded in return value as I64.

  • str, bytes: In both parameter and return positions. Written to extism memory; offset encoded in return value as I64.

  • int: In both parameter and return positions. Encoded as I64.

  • float: In both parameter and return positions. Encoded as F64.

  • bool: In both parameter and return positions. Encoded as I32.

  • typing.Tuple[<any of the above types>]: In return position; expands return list to include all member type encodings.

import typing
import extism

@extism.host_fn()
def greet(who: str) -> str:
    return "hello %s" % who

@extism.host_fn()
def load(input: typing.Annotated[dict, extism.Json]) -> typing.Tuple[int, int]:
    # input will be a dictionary decoded from json input. The tuple will be returned
    # two I64 values.
    return (3, 4)

@extism.host_fn()
def return_many_encoded() -> typing.Tuple(int, typing.Annotated[dict, extism.Json]):
    # we auto-encoded any Json-annotated return values, even in a tuple
    return (32, {"hello": "world"})

class Gromble:
    ...

@extism.host_fn()
def everyone_loves_a_pickle(grumble: typing.Annotated[Gromble, extism.Pickle]) -> typing.Annotated[Gromble, extism.Pickle]:
    # you can pass pickled objects in and out of host funcs
    return Gromble()

@extism.host_fn(signature=([extism.ValType.I64], []))
def more_control(
    current_plugin: extism.CurrentPlugin,
    params: typing.List[extism.Val],
    results: typing.List[extism.Val],
    *user_data
):
    # if you need more control, you can specify the wasm-level input
    # and output types explicitly.
    ...
class extism.Function(name, args, returns, f, *user_data)

A host function.

class extism.ValType(value, names=None, *, module=None, qualname=None, type=None, start=1, boundary=None)

An enumeration of all available Wasm value types.

class extism.Val(t, v)

Low-level WebAssembly value with associated ValType.

class extism.Codec(codec)

Typing metadata: indicates that an extism host function parameter (or return value) should be transformed with the provided function.

import json

@extism.host_fn()
def load(input: typing.Annotated[str, extism.Codec(lambda inp: inp.decode(encoding = 'shift_jis'))]):
    # you can accept shift-jis bytes as input!
    ...

mojibake_factory = lambda out: out.encode(encoding='utf8').decode(encoding='latin1').encode()

@extism.host_fn()
def load(input: int) -> typing.Annotated[str, extism.Codec(mojibake_factory)]:
    return "get ready for some mojibake 🎉"
class extism.Json

Typing metadata: indicates that an extism host function parameter (or return value) should be encoded (or decoded) using json.

@extism.host_fn()
def load(input: typing.Annotated[dict, extism.Json]):
    # input will be a dictionary decoded from json input.
    input.get("hello", None)

@extism.host_fn()
def load(input: int) -> typing.Annotated[dict, extism.Json]:
    return {
        'hello': 3
    }
class extism.Pickle

Typing metadata: indicates that an extism host function parameter (or return value) should be encoded (or decoded) using pickle.

class Grimace:
    ...

@extism.host_fn()
def load(input: typing.Annotated[Grimace, extism.Pickle]):
    # input will be an instance of Grimace!
    ...

@extism.host_fn()
def load(input: int) -> typing.Annotated[Grimace, extism.Pickle]:
    return Grimace()