| CARVIEW |
extism: Extism bindings
Downloads
- extism-1.3.0.0.tar.gz [browse] (Cabal source package)
- Package description (as included in the package)
Maintainer's Corner
For package maintainers and hackage trustees
Candidates
| Versions [RSS] | 0.1.0, 0.2.0, 0.3.0, 0.5.0, 1.0.0.0, 1.0.0.1, 1.1.0.0, 1.2.0.0, 1.2.0.1, 1.2.0.2, 1.2.0.3, 1.2.1.0, 1.3.0.0 |
|---|---|
| Change log | CHANGELOG.md |
| Dependencies | base (>=4.16.1 && <5), binary (>=0.8.9 && <0.9.0), bytestring (>=0.11.3 && <=0.12), extism-manifest (>=1.0.0 && <2.0.0), json (>=0.10 && <=0.11), uuid (>=1.3 && <2) [details] |
| License | BSD-3-Clause |
| Author | Extism authors |
| Maintainer | oss@extism.org |
| Uploaded | by zshipko at 2024-12-03T22:58:28Z |
| Category | Plugins, WebAssembly |
| Bug tracker | https://github.com/extism/haskell-sdk |
| Distributions | |
| Downloads | 713 total (57 in the last 30 days) |
| Rating | (no votes yet) [estimated by Bayesian average] |
| Your Rating |
|
| Status | Docs uploaded by user Build status unknown [no reports yet] |
Readme for extism-1.3.0.0
[back to package description]Extism Haskell Host SDK
This repo contains the Haskell package for integrating with the Extism runtime.
Note: If you're unsure what Extism is or what an SDK is see our homepage: https://extism.org.
Documentation
Documentation is available at https://hackage.haskell.org/package/extism
Installation
Install the Extism Runtime Dependency
For this library, you first need to install the Extism Runtime. You can download the shared object directly from a release or use the Extism CLI to install it.
Add the library to dune
Then add extism to your cabal file:
library
build-depends: extism
Getting Started
This guide should walk you through some of the concepts in Extism and the Haskell bindings.
Creating A Plug-in
The primary concept in Extism is the plug-in. You can think of a plug-in as a code module stored in a .wasm file.
Since you may not have an Extism plug-in on hand to test, let's load a demo plug-in from the web:
module Main where
import Extism
main = do
plugin <- unwrap <$> newPlugin (manifest [wasm]) [] True
res <- unwrap <$> call plugin "count_vowels" "Hello, world!"
putStrLn res
where
wasm = wasmURL "GET" "https://github.com/extism/plugins/releases/latest/download/count_vowels.wasm"
-- Prints: {"count":3,"total":3,"vowels":"aeiouAEIOU"}"
Note: See the Manifest docs as it has a rich schema and a lot of options.
This plug-in was written in Rust and it does one thing, it counts vowels in a string. As such, it exposes one "export" function: count_vowels. We can call exports using Extism.call:
All exports have a simple interface of bytes-in and bytes-out. This plug-in happens to take a string and return a JSON encoded string with a report of results.
This library also allowes for conversion of input/outputs types using FromBytes and ToBytes
Plug-in State
Plug-ins may be stateful or stateless. Plug-ins can maintain state b/w calls by the use of variables. Our count vowels plug-in remembers the total number of vowels it's ever counted in the "total" key in the result. You can see this by making subsequent calls to the export:
ghci> unwrap <$> call plugin "count_vowels" "Hello, world!"
{"count":3,"total":9,"vowels":"aeiouAEIOU"}
ghci> unwrap <$> call plugin "count_vowels" "Hello, world!"
{"count":3,"total":12,"vowels":"aeiouAEIOU"}
These variables will persist until this plug-in is freed or you initialize a new one.
Configuration
Plug-ins may optionally take a configuration object. This is a static way to configure the plug-in. Our count-vowels plugin takes an optional configuration to change out which characters are considered vowels. Example:
ghci> let manifest = manifest [wasm]
ghci> plugin <- unwrap <$> newPlugin manifest [] True
ghci> res <- (unwrap <$> call plugin "count_vowels" "Yellow, world!" :: String)
ghci> res
{"count":3,"total":3,"vowels":"aeiouAEIOU"}
ghci> plugin <- withConfig (manifest [wasm]) [("vowels","aeiouyAEIOUY")] ;;
ghci> res <- (unwrap <$> call plugin "count_vowels" "Yellow, world!" :: String)
ghci> res
{"count":4,"total":4,"vowels":"aeiouAEIOUY"}
Host Functions
Let's extend our count-vowels example a little bit: we can intercept the results and adjust them before returning from the plugin using a hello_world host function
with wasm/code-functions.wasm
Host functions allow us to grant new capabilities to our plug-ins from our application. They are simply some OCaml functions you write which can be passed down and invoked from any language inside the plug-in.
Using Extism.HostFunction.hostFunction we can define a host function that can be called from the guest plug-in.
In this example, we want to expose a single function to our plugin (in Haskell types): hello_world :: String -> String which will intercept the original result and replace it with a new one.
Let's load the manifest like usual but load up wasm/code-functions.wasm plug-in:
{-# LANGUAGE DeriveDataTypeable #-}
module Main where
import Extism
import Extism.HostFunction
import Extism.JSON
import Extism.Manifest (manifest, wasmFile)
newtype Count = Count {count :: Int} deriving (Data, Show)
hello currPlugin msg = do
putStrLn . unwrap <$> input currPlugin 0
putStrLn "Hello from Haskell!"
putStrLn msg
output currPlugin 0 (JSON $ Count 999)
main = do
setLogFile "stdout" LogError
f <- newFunction "hello_world" [ptr] [ptr] "Hello, again" hello
plugin <- unwrap <$> newPlugin m [f] True
id <- pluginID plugin
print id
JSON res <- (unwrap <$> call plugin "count_vowels" "this is a test" :: IO (JSON Count))
print res
where
m = manifest [wasmFile "wasm/code-functions.wasm"]
-- Prints: Count {count = 999}
Note: In order to write host functions you should get familiar with the methods on the Extism.HostFunction module.