| Copyright | (c) 2026 Tushar Adhatrao |
|---|---|
| License | MIT |
| Stability | experimental |
| Safe Haskell | None |
| Language | GHC2021 |
WasmEdge.Function.Memory
Description
Provides utilities for writing host functions that work with complex Haskell types by automatically marshalling them through Wasm linear memory.
The problem
WebAssembly functions can only pass numeric values (i32, i64, f32, f64)
across the FFI boundary. To call a host function with a Text argument or
return a [Double], the convention is:
- The guest writes the data into its linear memory.
- The guest passes the
(ptr: i32, len: i32)pair as function arguments. - The host reads the bytes from the calling frame's memory and deserialises.
liftMemFunc automates this entire read-deserialise-compute-serialise-write
pipeline for host functions.
Usage
-- A host function that takes Text input and returns Text output:
myGreeter :: Text -> IO (Either WasmEdgeError Text)
myGreeter name = pure (Right ("Hello, " <> name <> "!"))
-- Register it as a host function with signature (i32, i32) -> i64:
fn <- liftMemFunc myGreeter
withFunction someType fn $ \hostFn -> ...
The Wasm guest calls it as:
let ptr = alloc(len);
store_str(ptr, input_str);
let result_packed = greet(ptr, len);
let ret_ptr = (result_packed >> 32) as i32;
let ret_len = (result_packed & 0xFFFFFFFF) as i32;
Result encoding
Return values are packed as a single i64: upper 32 bits = output pointer,
lower 32 bits = output length. The output buffer is written into a scratch
region of Wasm linear memory.
For host functions that do not return data (only side effects), use
liftMemFunc_.
Synopsis
- liftMemFunc :: (WasmMemory a, WasmMemory b) => (a -> IO (Either WasmEdgeError b)) -> CallingFrame -> [WasmVal] -> IO (WasmResult [WasmVal])
- liftMemFunc_ :: WasmMemory a => (a -> IO (Either WasmEdgeError ())) -> CallingFrame -> [WasmVal] -> IO (WasmResult [WasmVal])
- liftMemFuncWith :: (WasmMemory a, WasmMemory b) => VM -> String -> AllocConvention -> (a -> IO (Either WasmEdgeError b)) -> CallingFrame -> [WasmVal] -> IO (WasmResult [WasmVal])
- callingFrameMemory :: CallingFrame -> IO (WasmResult MemoryInstance)
Lifting host functions
Arguments
| :: (WasmMemory a, WasmMemory b) | |
| => (a -> IO (Either WasmEdgeError b)) | The Haskell function to lift |
| -> CallingFrame | |
| -> [WasmVal] | |
| -> IO (WasmResult [WasmVal]) |
Lift a Haskell function a -> IO (Either WasmEdgeError b) into a raw
HostFunc that marshals arguments through Wasm linear memory.
The generated host function:
- Expects two
i32arguments:(ptr, len)— the pointer and length of the input buffer in Wasm linear memory. - Reads and deserialises
afrom that buffer usingwasmPeek. - Runs the user function.
- Serialises
binto a scratch region of Wasm linear memory at 1 MiB offset. - Returns a single
i64with(retPtr << 32 | retLen).
The function type to register with createFunction is [I32, I32] -> [I64].
Note: The scratch-region approach works for output up to ~63 MiB. For
larger outputs or when the Wasm module manages its own heap, use
liftMemFuncWith instead.
liftMemFunc_ :: WasmMemory a => (a -> IO (Either WasmEdgeError ())) -> CallingFrame -> [WasmVal] -> IO (WasmResult [WasmVal]) #
Like liftMemFunc but for functions with no return value (pure side-effects).
The generated host function returns no values.
The function type for createFunction is [I32, I32] -> [].
Arguments
| :: (WasmMemory a, WasmMemory b) | |
| => VM | The VM (used to call the guest's |
| -> String | Module name (identifies which module's |
| -> AllocConvention | Allocation convention (names the |
| -> (a -> IO (Either WasmEdgeError b)) | |
| -> CallingFrame | |
| -> [WasmVal] | |
| -> IO (WasmResult [WasmVal]) |
Advanced variant of liftMemFunc that uses the AllocConvention to
call the guest's alloc export for output buffer management.
This is the production-grade approach: the guest controls the heap, and the
host allocates an output buffer via alloc before writing the result. The
VM reference is needed to call back into the guest's alloc export.
The generated host function signature is [I32, I32] -> [I64] (same as
liftMemFunc).
Helper: get memory from calling frame
callingFrameMemory :: CallingFrame -> IO (WasmResult MemoryInstance) #
Get the linear memory instance from a CallingFrame.
The calling frame always has memory index 0 available if the guest module declares linear memory, which all practical Wasm modules do.
Returns Left if no linear memory is available (null pointer from C API).