Skip to content

Conversation

chrisdickinson
Copy link
Contributor

@chrisdickinson chrisdickinson commented Oct 13, 2023

Infer host function Wasm types from type annotations if given. When inferred, parameters and return values are automatically marshaled and unmarshaled and "current plugin" access is hidden. Whenever a host function is declared, add it to a thread-local registry of host functions. Default Plugin creation will use the global list of plugins.

In the weeds note: because this means we have to hang on to functions at specific addresses, we always end up using user_data now: in particular we store the offset of the target host function in the user_data to determine which implementation to call. I added this because the FFI call would fail if the target python host function wasn't available at module-level; this would turn into a stack overflow (it appeared that the runtime tried to re-invoke a host function infinitely if it couldn't find it.)


Example of inferred decorator + global host func registry:

import typings
import extism
@extism.host_fn()
def incr_json(input: typings.Annotated[dict, extism.Json]) -> str
    return input.get("hello", "world")

with extism.Plugin(some_wasm_file) as plugin:
    plugin.call("incr_json", json.dumps({"hello", "earth"}))

Infer host function Wasm types from type annotations if given. When inferred,
parameters and return values are automatically marshaled and unmarshaled and
"current plugin" access is hidden. Whenever a host function is declared, add it
to a thread-local registry of host functions. Default `Plugin` creation will
use the global list of plugins.

In the weeds note: because this means we have to hang on to functions at
specific addresses, we always end up using user_data now: in particular we
store the offset of the target host function in the user_data to determine
which implementation to call. I added this because the FFI call would fail if
the target python host function wasn't available at module-level; this would
turn into a stack overflow (it appeared that the runtime tried to re-invoke a
host function infinitely if it couldn't find it.)
@chrisdickinson chrisdickinson force-pushed the chris/20231013-infer-types branch from 43e4068 to ee9abf5 Compare October 13, 2023 22:05
Copy link
Contributor

@zshipko zshipko left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is really nice!

The one thing I'm unclear about is if it's possible to a user to write their own encoding format (like Json or Pickle)? If not, maybe we could provide an abstract class users could implement - which also could be a big enough chunk of work for a separate PR. But for now it seems fine as-is since they could always use a string/bytes argument and decode it themselves.

example.py Outdated
@host_fn
def hello_world(plugin, input_, output, a_string):
@host_fn(user_data=b"Hello again!")
def hello_world(inp: str, *a_string) -> str:
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is much more clear!

@chrisdickinson
Copy link
Contributor Author

@zshipko thanks – and great idea! I've added an extism.Codec class for use as a type annotation in the latest commit.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants