Skip to content

Commit

Permalink
feat: add host context
Browse files Browse the repository at this point in the history
  • Loading branch information
zshipko committed Nov 25, 2024
1 parent 3a5ca56 commit 9704be4
Show file tree
Hide file tree
Showing 4 changed files with 79 additions and 0 deletions.
13 changes: 13 additions & 0 deletions src/bindings.ml
Original file line number Diff line number Diff line change
Expand Up @@ -128,6 +128,19 @@ let extism_plugin_call_s =
fn "extism_plugin_call"
(plugin @-> string @-> string @-> uint64_t @-> returning int32_t)

let extism_current_plugin_host_context =
fn "extism_current_plugin_host_context" (ptr void @-> returning (ptr void))

let extism_plugin_call_with_host_contet =
fn "extism_plugin_call_with_host_context"
(plugin @-> string @-> ptr char @-> uint64_t @-> ptr void
@-> returning int32_t)

let extism_plugin_call_s_with_host_context =
fn "extism_plugin_call_with_host_context"
(plugin @-> string @-> string @-> uint64_t @-> ptr void
@-> returning int32_t)

let extism_error = fn "extism_plugin_error" (plugin @-> returning string_opt)

let extism_plugin_output_length =
Expand Down
25 changes: 25 additions & 0 deletions src/extism.mli
Original file line number Diff line number Diff line change
Expand Up @@ -296,6 +296,9 @@ module Host_function : sig
val output : (module Type.S with type t = 'a) -> ?index:int -> t -> 'a -> unit
(** Convert a value, allocate it and update the results array at [index] *)

val host_context : t -> 'a option
(** Get configured host context *)

(** Some helpter functions for reading/writing memory *)
module Memory_handle : sig
val memory : ?offs:Unsigned.UInt64.t -> t -> Unsigned.uint8 Ctypes.ptr
Expand Down Expand Up @@ -421,6 +424,28 @@ module Plugin : sig
'b
(** Similar to {!call} but raises an exception using {!Error.unwrap} *)


val call_with_host_context :
(module Type.S with type t = 'a) ->
(module Type.S with type t = 'b) ->
t ->
ctx: 'c ->
name:string ->
'a ->
('b, Error.t) result
(** [call_with_host_context input_type output_type t ~ctx ~name input] executes a function with input
and output types defined in {!Type} *)

val call_with_host_context_exn :
(module Type.S with type t = 'a) ->
(module Type.S with type t = 'b) ->
t ->
ctx:'c ->
name:string ->
'a ->
'b
(** Similar to {!call_with_host_context} but raises an exception using {!Error.unwrap} *)

val free : t -> unit
(** Free a plugin immediately, this isn't normally required unless there are a
lot of plugins open at once *)
Expand Down
4 changes: 4 additions & 0 deletions src/host_function.ml
Original file line number Diff line number Diff line change
Expand Up @@ -103,3 +103,7 @@ let input (type a) (module C : Type.S with type t = a) ?index t =
C.decode bs

let input_exn a ?index t = input a ?index t |> Error.unwrap

let host_context t =
let ptr = Bindings.extism_current_plugin_host_context t.pointer in
if Ctypes.is_null ptr then None else Some (Ctypes.Root.get ptr)
37 changes: 37 additions & 0 deletions src/plugin.ml
Original file line number Diff line number Diff line change
Expand Up @@ -98,6 +98,26 @@ let call' f { pointer; _ } ~name input len =
in
Ok buf

let call_with_host_context' f { pointer; _ } ~name input len ctx =
if Ctypes.is_null pointer then Error.throw (`Msg "Plugin already freed")
else
let root = Ctypes.Root.create ctx in
let rc = f pointer name input len root in
let err = Bindings.extism_error pointer in
if rc <> 0l || Option.is_some err then
match err with
| None -> Error (`Msg "extism_plugin_call failed")
| Some msg -> Error (`Msg msg)
else
let out_len = Bindings.extism_plugin_output_length pointer in
let ptr = Bindings.extism_plugin_output_data pointer in
let buf =
Ctypes.bigarray_of_ptr Ctypes.array1
(Unsigned.UInt64.to_int out_len)
Char ptr
in
Ok buf

let call_bigstring (t : t) ~name input =
let len = Unsigned.UInt64.of_int (Bigstringaf.length input) in
let ptr = Ctypes.bigarray_start Ctypes.array1 input in
Expand Down Expand Up @@ -135,6 +155,23 @@ let call (type a b) (module In : Type.S with type t = a)

let call_exn a b t ~name input = call a b t ~name input |> Error.unwrap

let call_with_host_context (type a b) (module In : Type.S with type t = a)
(module Out : Type.S with type t = b) t ~ctx ~name (a : a) :
(b, Error.t) result =
let input = In.encode a in
let len = String.length input in
match
call_with_host_context' Bindings.extism_plugin_call_s_with_host_context t
~name input
(Unsigned.UInt64.of_int len)
ctx
with
| Ok x -> Out.decode x
| Error e -> Error e

let call_with_host_context_exn a b t ~ctx ~name input =
call_with_host_context a b t ~ctx ~name input |> Error.unwrap

let%test "call" =
let manifest = Manifest.(create [ Wasm.file "test/code.wasm" ]) in
let plugin = of_manifest manifest |> Error.unwrap in
Expand Down

0 comments on commit 9704be4

Please sign in to comment.