diff --git a/examples/basic.zig b/examples/basic.zig index 303e7a3..f6d51b7 100644 --- a/examples/basic.zig +++ b/examples/basic.zig @@ -2,6 +2,7 @@ const std = @import("std"); const sdk = @import("extism"); const Plugin = sdk.Plugin; const CurrentPlugin = sdk.CurrentPlugin; +const CompiledPlugin = sdk.CompiledPlugin; const Function = sdk.Function; const manifest = sdk.manifest; @@ -24,7 +25,7 @@ pub fn main() !void { _ = sdk.setLogFile("extism.log", .Debug); const wasmfile_manifest = manifest.WasmFile{ .path = "wasm/code-functions.wasm" }; - const man = .{ .wasm = &[_]manifest.Wasm{.{ .wasm_file = wasmfile_manifest }} }; + const man = manifest.Manifest{ .wasm = &[_]manifest.Wasm{.{ .wasm_file = wasmfile_manifest }} }; var f = Function.init( "hello_world", &[_]sdk.c.ExtismValType{sdk.PTR}, @@ -33,7 +34,10 @@ pub fn main() !void { @constCast(@as(*const anyopaque, @ptrCast("user data"))), ); defer f.deinit(); - var my_plugin = try Plugin.initFromManifest(allocator, man, &[_]Function{f}, true); + var c = try CompiledPlugin.initFromManifest(allocator, man, &[_]Function{f}, true); + defer c.deinit(); + + var my_plugin = try Plugin.initFromCompiled(c); defer my_plugin.deinit(); var config = std.json.ArrayHashMap([]const u8){}; diff --git a/src/compiled_plugin.zig b/src/compiled_plugin.zig new file mode 100644 index 0000000..e9fa9cc --- /dev/null +++ b/src/compiled_plugin.zig @@ -0,0 +1,54 @@ +const std = @import("std"); +const Manifest = @import("manifest.zig").Manifest; +const Function = @import("function.zig"); +const CancelHandle = @import("cancel_handle.zig"); +const c = @import("ffi.zig"); + +const Self = @This(); + +ptr: *c.ExtismCompiledPlugin, + +// We have to use this until ziglang/zig#2647 is resolved. +error_info: ?[]const u8, + +/// Create a new plugin from a WASM module +pub fn init(allocator: std.mem.Allocator, data: []const u8, functions: []const Function, wasi: bool) !Self { + var plugin: ?*c.ExtismCompiledPlugin = null; + var errmsg: [*c]u8 = null; + if (functions.len > 0) { + var funcPtrs = try allocator.alloc(?*c.ExtismFunction, functions.len); + defer allocator.free(funcPtrs); + var i: usize = 0; + for (functions) |function| { + funcPtrs[i] = function.c_func; + i += 1; + } + plugin = c.extism_compiled_plugin_new(data.ptr, @as(u64, data.len), &funcPtrs[0], functions.len, wasi, &errmsg); + } else { + plugin = c.extism_compiled_plugin_new(data.ptr, @as(u64, data.len), null, 0, wasi, &errmsg); + } + + if (plugin == null) { + // TODO: figure out what to do with this error + std.debug.print("extism_compiled_plugin_new: {s}", .{ + errmsg, + }); + c.extism_plugin_new_error_free(errmsg); + return error.PluginLoadFailed; + } + return Self{ + .ptr = plugin.?, + .error_info = null, + }; +} + +/// Create a new plugin from the given manifest +pub fn initFromManifest(allocator: std.mem.Allocator, manifest: Manifest, functions: []const Function, wasi: bool) !Self { + const json = try std.json.stringifyAlloc(allocator, manifest, .{ .emit_null_optional_fields = false }); + defer allocator.free(json); + return init(allocator, json, functions, wasi); +} + +pub fn deinit(self: *Self) void { + c.extism_compiled_plugin_free(self.ptr); +} diff --git a/src/main.zig b/src/main.zig index 174ef8e..96f83b2 100644 --- a/src/main.zig +++ b/src/main.zig @@ -3,6 +3,7 @@ const testing = std.testing; pub const c = @import("ffi.zig"); pub const Plugin = @import("plugin.zig"); +pub const CompiledPlugin = @import("compiled_plugin.zig"); pub const CurrentPlugin = @import("current_plugin.zig"); pub const CancelHandle = @import("cancel_handle.zig"); pub const Function = @import("function.zig"); diff --git a/src/plugin.zig b/src/plugin.zig index 23e5d86..ae76241 100644 --- a/src/plugin.zig +++ b/src/plugin.zig @@ -3,6 +3,7 @@ const Manifest = @import("manifest.zig").Manifest; const Function = @import("function.zig"); const CancelHandle = @import("cancel_handle.zig"); const c = @import("ffi.zig"); +const CompiledPlugin = @import("compiled_plugin.zig"); const Self = @This(); @@ -49,6 +50,21 @@ pub fn initFromManifest(allocator: std.mem.Allocator, manifest: Manifest, functi return init(allocator, json, functions, wasi); } +/// Create a new plugin from a pre-compiled plugin +pub fn initFromCompiled(compiled: *CompiledPlugin) !Self { + var errmsg: [*c]u8 = null; + const plugin = c.extism_plugin_new_from_compiled(compiled.ptr, &errmsg); + if (plugin == null) { + // TODO: figure out what to do with this error + std.debug.print("extism_plugin_new: {s}", .{ + errmsg, + }); + c.extism_plugin_new_error_free(errmsg); + return error.PluginLoadFailed; + } + return plugin; +} + pub fn deinit(self: *Self) void { c.extism_plugin_free(self.ptr); }