{"id":13611875,"url":"https://github.com/extism/zig-sdk","last_synced_at":"2025-07-16T14:35:12.664Z","repository":{"id":194645304,"uuid":"691134782","full_name":"extism/zig-sdk","owner":"extism","description":"Extism Zig Host SDK - easily run WebAssembly modules / plugins from Zig applications","archived":false,"fork":false,"pushed_at":"2025-04-29T15:02:11.000Z","size":1615,"stargazers_count":29,"open_issues_count":1,"forks_count":3,"subscribers_count":6,"default_branch":"main","last_synced_at":"2025-06-27T09:05:41.025Z","etag":null,"topics":[],"latest_commit_sha":null,"homepage":"https://extism.org","language":"Zig","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"bsd-3-clause","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/extism.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":".github/CODEOWNERS","security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null,"zenodo":null}},"created_at":"2023-09-13T15:09:03.000Z","updated_at":"2025-04-29T15:02:15.000Z","dependencies_parsed_at":"2024-01-15T02:30:04.924Z","dependency_job_id":"2e2a7985-0bf8-4ab4-a20f-d422e86f698f","html_url":"https://github.com/extism/zig-sdk","commit_stats":null,"previous_names":["extism/zig-sdk"],"tags_count":4,"template":false,"template_full_name":null,"purl":"pkg:github/extism/zig-sdk","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/extism%2Fzig-sdk","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/extism%2Fzig-sdk/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/extism%2Fzig-sdk/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/extism%2Fzig-sdk/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/extism","download_url":"https://codeload.github.com/extism/zig-sdk/tar.gz/refs/heads/main","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/extism%2Fzig-sdk/sbom","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":265518503,"owners_count":23780971,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":[],"created_at":"2024-08-01T19:02:16.817Z","updated_at":"2025-07-16T14:35:12.642Z","avatar_url":"https://github.com/extism.png","language":"Zig","funding_links":[],"categories":["Zig"],"sub_categories":[],"readme":"# Extism Zig Host SDK\n\nThis repo contains the Zig code for integrating with the [Extism](https://extism.org/) runtime. Install this library into your host Zig application to run Extism plug-ins.\n\n\u003e **Note**: If you're unsure what Extism is or what an SDK is see our homepage: [https://extism.org](https://extism.org).\n\n## Installation\n\n### Install the Extism Runtime Dependency\n\nFor this library, you first need to install the Extism Runtime. You can [download the shared object directly from a release](https://github.com/extism/extism/releases) or use the [Extism CLI](https://github.com/extism/cli) to install it:\n\n```bash\nsudo extism lib install latest\n\n#=\u003e Fetching https://github.com/extism/extism/releases/download/v0.5.2/libextism-aarch64-apple-darwin-v0.5.2.tar.gz\n#=\u003e Copying libextism.dylib to /usr/local/lib/libextism.dylib\n#=\u003e Copying extism.h to /usr/local/include/extism.h\n```\n\n# within your Zig project directory:\n\n```\nzig fetch --save https://github.com/extism/zig-sdk/archive/\u003cgit-ref-here\u003e.tar.gz\n```\n\nAnd in your `build.zig`:\n```zig\n// to use the build script util, import extism:\nconst extism = @import(\"extism\");\n\n// inside your `build` function, after you've created tests or an executable step:\nextism.addLibrary(exe, b);\n```\n\n## Getting Started\n\nThis guide should walk you through some of the concepts in Extism and this Zig library.\n\n### Creating A Plug-in\n\nThe primary concept in Extism is the [plug-in](https://extism.org/docs/concepts/plug-in). You can think of a plug-in as a code module stored in a `.wasm` file.\n\nSince you may not have an Extism plug-in on hand to test, let's load a demo plug-in from the web:\n\n```zig\n// First require the library\nconst extism = @import(\"extism\");\nconst std = @import(\"std\");\n\nconst wasm_url = extism.manifest.WasmUrl{ .url = \"https://github.com/extism/plugins/releases/latest/download/count_vowels.wasm\" };\nconst manifest = extism.manifest.Manifest{ .wasm = \u0026[_]extism.manifest.Wasm{.{ .wasm_url= wasm_url }} };\n\nvar gpa = std.heap.GeneralPurposeAllocator(.{}){};\ndefer std.debug.assert(gpa.deinit() == .ok);\nconst allocator = gpa.allocator();\n\nvar plugin = try extism.Plugin.initFromManifest(\n    allocator,\n    manifest,\n    \u0026[_]extism.Function{},\n    false,  \n);\n\ndefer plugin.deinit();\n```\n\n\u003e **Note**: See [the Manifest docs](https://github.com/extism/zig-sdk/blob/main/src/manifest.zig#L32) as it has a rich schema and a lot of options.\n\n### Calling A Plug-in's Exports\n\nThis 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::Plugin#call](https://github.com/extism/zig-sdk/blob/main/src/plugin.zig#L61):\n\n```zig\ntry plugin.call(\"count_vowels\", \"Hello, World!\");\n# =\u003e {\"count\": 3, \"total\": 3, \"vowels\": \"aeiouAEIOU\"}\n```\n\nAll 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.\n\n### Plug-in State\n\nPlug-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:\n\n```zig\ntry plugin.call(\"count_vowels\", \"Hello, World!\");\n# =\u003e {\"count\": 3, \"total\": 6, \"vowels\": \"aeiouAEIOU\"}\ntry plugin.call(\"count_vowels\", \"Hello, World!\");\n# =\u003e {\"count\": 3, \"total\": 9, \"vowels\": \"aeiouAEIOU\"}\n```\n\nThese variables will persist until this plug-in is freed or you initialize a new one.\n\n### Configuration\n\nPlug-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:\n\n```zig\ntry plugin.call(\"count_vowels\", \"Yellow, World!\");\n# =\u003e {\"count\": 3, \"total\": 3, \"vowels\": \"aeiouAEIOU\"}\n\nvar config = std.json.ArrayHashMap([]const u8){};\ndefer config.deinit(allocator);\n\ntry config.map.put(allocator, \"vowels\", \"aeiouyAEIOUY\");\ntry plugin.setConfig(allocator, config);\n\ntry plugin.call(\"count_vowels\", \"Yellow, World!\");\n# =\u003e {\"count\": 4, \"total\": 4, \"vowels\": \"aeiouAEIOUY\"}\n```\n\n### Host Functions\n\nLet's extend our count-vowels example a little bit: Instead of storing the `total` in an ephemeral plug-in var, let's store it in a persistent key-value store!\n\nWasm can't use our KV store on it's own. This is where [Host Functions](https://extism.org/docs/concepts/host-functions) come in.\n\n[Host functions](https://extism.org/docs/concepts/host-functions) allow us to grant new capabilities to our plug-ins from our application. They are simply some zig methods you write which can be passed down and invoked from any language inside the plug-in.\n\nLet's load the manifest like usual but load up this `count_vowels_kvstore` plug-in:\n\n```zig\nconst wasm_url = extism.manifest.WasmUrl{ .url = \"https://github.com/extism/plugins/releases/latest/download/count_vowels_kvstore.wasm\" };\nconst manifest = extism.manifest.Manifest{ .wasm = \u0026[_]extism.manifest.Wasm{.{ .wasm_url= wasm_url }} };\n```\n\n\u003e *Note*: The source code for this is [here](https://github.com/extism/plugins/blob/main/count_vowels_kvstore/src/lib.rs) and is written in rust, but it could be written in any of our PDK languages.\n\nUnlike our previous plug-in, this plug-in expects you to provide host functions that satisfy our its import interface for a KV store.\n\nWe want to expose two functions to our plugin, `kv_write(key: String, value: Bytes)` which writes a bytes value to a key and `kv_read(key: String) -\u003e Bytes` which reads the bytes at the given `key`.\n\n```zig\n// pretend this is Redis or something\nvar KV_STORE: std.StringHashMap(u32) = undefined;\n\nexport fn kv_read(caller: ?*extism.c.ExtismCurrentPlugin, inputs: [*c]const extism.c.ExtismVal, n_inputs: u64, outputs: [*c]extism.c.ExtismVal, n_outputs: u64, user_data: ?*anyopaque) callconv(.C) void {\n    _ = user_data;\n    var curr_plugin = extism.CurrentPlugin.getCurrentPlugin(caller orelse unreachable);\n\n    // retrieve the key from the plugin\n    var input_slice = inputs[0..n_inputs];\n    const key = curr_plugin.inputBytes(\u0026input_slice[0]);\n\n    var out = outputs[0..n_outputs];\n    // Try to get the value from KV_STORE\n    if (KV_STORE.get(key)) |val| {\n        // return the value to the plugin\n        var data: [4]u8 = undefined;\n        std.mem.writeInt(u32, \u0026data, val, .little);\n        curr_plugin.returnBytes(\u0026out[0], \u0026data);\n    } else {\n        KV_STORE.put(key, 0) catch unreachable;\n        curr_plugin.returnBytes(\u0026out[0], \u0026[4]u8{ 0, 0, 0, 0 });\n    }\n}\n\nexport fn kv_write(caller: ?*extism.c.ExtismCurrentPlugin, inputs: [*c]const extism.c.ExtismVal, n_inputs: u64, outputs: [*c]extism.c.ExtismVal, n_outputs: u64, user_data: ?*anyopaque) callconv(.C) void {\n    _ = user_data;\n    _ = outputs;\n    _ = n_outputs;\n    var curr_plugin = extism.CurrentPlugin.getCurrentPlugin(caller orelse unreachable);\n\n    // retrieve key and value from the plugin\n    var in = inputs[0..n_inputs];\n    const key = curr_plugin.inputBytes(\u0026in[0]);\n    const val = curr_plugin.inputBytes(\u0026in[1]);\n\n    // write to the KV\n    KV_STORE.put(key, std.mem.readInt(u32, val[0..4], .little)) catch unreachable;\n}\n\n```\n\nNow we just need to create a new host environment and pass it in when loading the plug-in. Here our environment initializer takes no arguments, but you could imagine putting some customer specific instance variables in there:\n\n```zig\n var gpa = std.heap.GeneralPurposeAllocator(.{}){};\nconst allocator = gpa.allocator();\n\nKV_STORE = std.StringHashMap([]const u8).init(allocator);\ndefer KV_STORE.deinit();\n\nvar f_read = extism.Function.init(\n    \"kv_read\",\n    \u0026[_]extism.c.ExtismValType{extism.PTR},\n    \u0026[_]extism.c.ExtismValType{extism.PTR},\n    \u0026kv_read,\n    @constCast(@as(*const anyopaque, @ptrCast(\"user data\"))),\n);\ndefer f_read.deinit();\n\nvar f_write = extism.Function.init(\n    \"kv_write\",\n    \u0026[_]extism.c.ExtismValType{extism.PTR, extism.PTR},\n    \u0026[_]extism.c.ExtismValType{},\n    \u0026kv_write,\n    @constCast(@as(*const anyopaque, @ptrCast(\"user data\"))),\n);\ndefer f_write.deinit();\n\nvar plugin = try extism.Plugin.initFromManifest(\n    allocator,\n    manifest,\n    \u0026[_]extism.Function{f_read, f_write},\n    false,  \n);\ndefer plugin.deinit();\n```\n\nNow we can invoke the event:\n\n```zig\ntry plugin.call(\"count_vowels\", \"Hello, World!\");\n# =\u003e {\"count\": 3, \"total\": 3, \"vowels\": \"aeiouAEIOU\"}\n\ntry plugin.call(\"count_vowels\", \"Hello, World!\");\n# =\u003e {\"count\": 3, \"total\": 6, \"vowels\": \"aeiouAEIOU\"}\n```\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fextism%2Fzig-sdk","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fextism%2Fzig-sdk","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fextism%2Fzig-sdk/lists"}