Skip to content

Commit 4bda29d

Browse files
feat: enable compiled plugins
Add `extism.CompiledPlugin`, which may be provided as the `wasm` parameter to `extism.Plugin`.
1 parent 4e5051d commit 4bda29d

File tree

1 file changed

+59
-15
lines changed

1 file changed

+59
-15
lines changed

extism/extism.py

+59-15
Original file line numberDiff line numberDiff line change
@@ -431,6 +431,58 @@ def cancel(self) -> bool:
431431
return _lib.extism_plugin_cancel(self.pointer)
432432

433433

434+
class CompiledPlugin:
435+
"""
436+
A ``CompiledPlugin`` represents a parsed Wasm module and associated Extism
437+
kernel. It can be used to rapidly instantiate plugin instances. A ``Plugin``
438+
instantiated with a ``CompiledPlugin`` inherits the functions and WASI settings
439+
of the compiled plugin.
440+
441+
.. sourcecode:: python
442+
443+
import extism
444+
445+
compiled = extism.CompiledPlugin({
446+
wasm: [
447+
{ 'url': 'https://example.com/path/to/module.wasm' }
448+
],
449+
})
450+
451+
plugin = extism.Plugin(compiled)
452+
plugin.call("example-function")
453+
"""
454+
455+
def __init__(
456+
self,
457+
plugin: Union[str, bytes, dict],
458+
wasi: bool = False,
459+
functions: Optional[List[Function]] = HOST_FN_REGISTRY,
460+
):
461+
wasm = _wasm(plugin)
462+
self.functions = functions
463+
as_extism_functions = [_ExtismFunctionMetadata(f) for f in functions or []]
464+
as_ptrs = [f.pointer for f in as_extism_functions]
465+
# Register plugin
466+
errmsg = _ffi.new("char**")
467+
function_ptrs = (
468+
_ffi.NULL if len(as_ptrs) == 0 else _ffi.new("ExtismFunction*[]", as_ptrs)
469+
)
470+
self.pointer = _lib.extism_compiled_plugin_new(
471+
wasm, len(wasm), function_ptrs, len(as_ptrs), wasi, errmsg
472+
)
473+
474+
if self.pointer == _ffi.NULL:
475+
msg = _ffi.string(errmsg[0])
476+
_lib.extism_plugin_new_error_free(errmsg[0])
477+
raise Error(msg.decode())
478+
479+
def __del__(self):
480+
if not hasattr(self, "pointer"):
481+
return
482+
_lib.extism_compiled_plugin_free(self.pointer)
483+
self.pointer = -1
484+
485+
434486
class Plugin:
435487
"""
436488
Plugins are used to call WASM functions. Plugins can kept in a context for
@@ -464,28 +516,20 @@ class Plugin:
464516

465517
def __init__(
466518
self,
467-
plugin: Union[str, bytes, dict],
519+
plugin: Union[str, bytes, CompiledPlugin, dict],
468520
wasi: bool = False,
469521
config: Optional[Any] = None,
470522
functions: Optional[List[Function]] = HOST_FN_REGISTRY,
471523
):
472-
wasm = _wasm(plugin)
473-
self.functions = functions
474-
as_extism_functions = [_ExtismFunctionMetadata(f) for f in functions or []]
524+
if not isinstance(plugin, CompiledPlugin):
525+
plugin = CompiledPlugin(plugin, wasi, functions)
475526

476-
# Register plugin
527+
self.compiled_plugin = plugin
477528
errmsg = _ffi.new("char**")
478-
if as_extism_functions is not None:
479-
function_ptrs = [f.pointer for f in as_extism_functions]
480-
ptr = _ffi.new("ExtismFunction*[]", function_ptrs)
481-
self.plugin = _lib.extism_plugin_new(
482-
wasm, len(wasm), ptr, len(function_ptrs), wasi, errmsg
483-
)
484-
else:
485-
self.plugin = _lib.extism_plugin_new(
486-
wasm, len(wasm), _ffi.NULL, 0, wasi, errmsg
487-
)
488529

530+
self.plugin = _lib.extism_plugin_new_from_compiled(
531+
self.compiled_plugin.pointer, errmsg
532+
)
489533
if self.plugin == _ffi.NULL:
490534
msg = _ffi.string(errmsg[0])
491535
_lib.extism_plugin_new_error_free(errmsg[0])

0 commit comments

Comments
 (0)