Class: Extism::Plugin

Inherits:
Object
  • Object
show all
Defined in:
lib/extism/plugin.rb

Overview

A Plugin represents an instance of your WASM program created from the given manifest.

Instance Method Summary collapse

Constructor Details

#initialize(wasm, environment: nil, functions: [], wasi: false, config: nil) ⇒ Plugin

Intialize a plugin

Examples:

Initialize a plugin from a url

manifest = Extism::Manifest.from_url "https://github.com/extism/plugins/releases/latest/download/count_vowels.wasm"
plugin = Extism::Plugin.new(manifest)

Pass a config object to configure the plug-in

plugin = Extism::Plugin.new(manifest, config: { hello: "world" })

Initalize a plug-in that needs WASI

plugin = Extism::Plugin.new(manifest, wasi: true)

Parameters:

  • wasm (Hash, String, Manifest)

    The manifest as a Hash or WASM binary as a String. See extism.org/docs/concepts/manifest/.

  • wasi (Boolean) (defaults to: false)

    Enable WASI support

  • config (Hash) (defaults to: nil)

    The plugin config



20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
# File 'lib/extism/plugin.rb', line 20

def initialize(wasm, environment: nil, functions: [], wasi: false, config: nil)
  wasm = case wasm
         when Hash
           JSON.generate(wasm)
         when Manifest
           JSON.generate(wasm.manifest_data)
         else
           wasm
         end

  code = FFI::MemoryPointer.new(:char, wasm.bytesize)
  errmsg = FFI::MemoryPointer.new(:pointer)
  code.put_bytes(0, wasm)
  if functions.empty? && environment
    unless environment.respond_to?(:host_functions)
      raise ArgumentError 'environment should implement host_functions method'
    end

    functions = environment.host_functions
  end
  funcs_ptr = FFI::MemoryPointer.new(LibExtism::ExtismFunction)
  funcs_ptr.write_array_of_pointer(functions.map { |f| f.send(:pointer) })
  @plugin = LibExtism.extism_plugin_new(code, wasm.bytesize, funcs_ptr, functions.length, wasi, errmsg)
  if @plugin.null?
    err = errmsg.read_pointer.read_string
    LibExtism.extism_plugin_new_error_free errmsg.read_pointer
    raise Error, err
  end
  $PLUGINS[object_id] = { plugin: @plugin }
  ObjectSpace.define_finalizer(self, $FREE_PLUGIN)
  return unless !config.nil? and @plugin.null?

  s = JSON.generate(config)
  ptr = FFI::MemoryPointer.from_string(s)
  LibExtism.extism_plugin_config(@plugin, ptr, s.bytesize)
end

Instance Method Details

#call(name, data, &block) ⇒ String

Call a function by name

Examples:

input = JSON.generate({hello: "world"})
result = plugin.call("my_func", input)
output = JSON.parse(result)

Parameters:

  • name (String)

    The function name

  • data (String)

    The input data for the function

Returns:

  • (String)

    The output from the function in String form



75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
# File 'lib/extism/plugin.rb', line 75

def call(name, data, &block)
  # If no block was passed then use Pointer::read_string
  block ||= ->(buf, len) { buf.read_string(len) }
  input = FFI::MemoryPointer.from_string(data)
  rc = LibExtism.extism_plugin_call(@plugin, name, input, data.bytesize)
  if rc != 0
    err = LibExtism.extism_plugin_error(@plugin)
    raise Error, 'extism_call failed' if err&.empty?

    raise Error, err

  end

  out_len = LibExtism.extism_plugin_output_length(@plugin)
  buf = LibExtism.extism_plugin_output_data(@plugin)
  block.call(buf, out_len)
end

#cancel_handleObject

Get a CancelHandle for a plugin



105
106
107
# File 'lib/extism/plugin.rb', line 105

def cancel_handle
  CancelHandle.new(LibExtism.extism_plugin_cancel_handle(@plugin))
end

#freevoid

This method returns an undefined value.

Free a plugin, this should be called when the plugin is no longer needed



96
97
98
99
100
101
102
# File 'lib/extism/plugin.rb', line 96

def free
  return if @plugin.null?

  $PLUGINS.delete(object_id)
  LibExtism.extism_plugin_free(@plugin)
  @plugin = nil
end

#has_function?(name) ⇒ Boolean

Check if a function exists

Parameters:

  • name (String)

    The name of the function

Returns:

  • (Boolean)

    Returns true if function exists



61
62
63
# File 'lib/extism/plugin.rb', line 61

def has_function?(name)
  LibExtism.extism_plugin_function_exists(@plugin, name)
end